在元素XML中使用多个模式

时间:2012-11-25 15:04:57

标签: xml xsd

我需要定义一个包含多个模式的元素,例如gDaygMonthgYeardateTime等。如何在中定义限制XSD 这样做?

像这样:

<dates>
    <out>2012</out>
</dates>


<xs:complexType name="infodates">
        <xs:sequence>
            <xs:element name="out" type="xs:dateTime"&"xs:gMonth"/>
        </xs:sequence>
</xs:complexType>

由于

2 个答案:

答案 0 :(得分:1)

这可以通过自定义模式作为TYPE来完成。 例如:

     <xs:simpleType name="CRNDATETIME">
        <xs:restriction base="xs:string">
          <xs:pattern value="|(((01|02|03|04|05|06|07|08|09|10|11|12)/(01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)/[1-2][0-9][0-9][0-9][ ](00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23)[:][0-5][0-9][:][0-5][0-9])|
                             ((01|02|03|04|05|06|07|08|09|10|11|12)/(01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)/[1-2][0-9][0-9][0-9][ ](01|02|03|04|05|06|07|08|09|10|11|12)[:][0-5][0-9][:][0-5][0-9] [aApP][mM]))"/>
        </xs:restriction>
      </xs:simpleType>

这接受以下模式的日期时间值
 1.MM / DD / YYYY hh:mm:ss aAmM / pPmM ..
 2. MM / DD / YYYY HH:mm:ss
也接受空值..

我知道这有点困难而非常困难......但是可以实现......

答案 1 :(得分:1)

简短回答:xml架构无法连接简单的数据类型。

它可能不是你想要的:xs:gMonth需要双连字符前缀(例如“--05”),xs:gDay需要三连字符(例如“--- 31 “)。不是我的预期! 这是examples for each simple datatype。内置了一些组合类型:gYearMonthgMonthDay等。

在这些方面,xs:dateTime有一个很长的定义:'-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?只剩下三个部分,因此它需要yyyy-mm-ddThh:mm:ss - 您<out>2012</out>中的示例不是对此有效。


长答案:但是,xml架构可以通过union(如选择)和list(相同类型的空格分隔列表)组合简单数据类型。所以,您可以执行以下操作:(gDay|gMonth|gYear|dateTime)*(不是有效的xsd语法,只是说明性的)。这不是有序的,并允许重复,所以例如“--- 31 - 05 - 05”有效。这是xsd语法:

$ cat catDatatypes.xsd 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="eg" type="myString_Type"/>
  <xs:simpleType name="myString_Type">
    <xs:list>
      <xs:simpleType>
        <xs:union>
          <xs:simpleType>
            <xs:restriction base="xs:gDay"/>
          </xs:simpleType>
          <xs:simpleType>
            <xs:restriction base="xs:gMonth"/>
          </xs:simpleType>
          <xs:simpleType>
            <xs:restriction base="xs:gYear"/>
          </xs:simpleType>
          <xs:simpleType>
            <xs:restriction base="xs:dateTime"/>
          </xs:simpleType>
        </xs:union>
      </xs:simpleType>
    </xs:list>
  </xs:simpleType>
</xs:schema>

$ xmllint --schema catDatatypes.xsd catDatatypes.xml 
<eg>2012 --12 ---01 --12 ---31 --05 --05</eg>
catDatatypes.xml validates

结论:您不能以您(和我)想要的方式重用内置数据类型,而且它们似乎也不是很好。你可能最好自己明确地定义它,就像InfantProgrammer'Aravind的回答一样。 (或者,您可以为每个组件使用单独的属性 - 这样也可以使解析它的人更容易。)


为了好玩,我尝试缩短InfantProgrammer'Aravind的答案(虽然这是否可以说明这是否更清楚......)。它保留了12小时的上午/下午与24小时没有上午/下午的检查(但不接受空的又名空值)。

 <xs:simpleType name="CRNDATETIME2">
    <xs:restriction base="xs:string">
      <xs:pattern value="(0[1-9]|1[012])/(0[1-9]|[12]\d|3[01])/([12]\d{3}) ((0\d|1[012])(:[0-5]\d){2}|(0\d|1[012])(:[0-5]\d){2} [aApP][mM])"/>
    </xs:restriction>
  </xs:simpleType>

这是XSD中的brief guide正则表达式;这是一个long one

BTW:结果你可以将“[1-9]”表示为“[\ d- [0]]”,这是一个"Character Class Subtraction",而不是一个范围。