如何从xsd序列中删除排序

时间:2014-04-16 08:07:03

标签: xml xsd xml-validation

如何删除以下xsd中的排序限制:

<xs:element name="example">
    <xs:sequence>
        <xs:element name="hostname" type="xs:string" minOccurs="0" maxOccurs="1"/>
        <xs:element name="filename" type="xs:string" minOccurs="1" maxOccurs="1"/>
        <xs:element name="chunks" type="xs:string" minOccurs="1" maxOccurs="unbonded"/>
    </xs:sequence>
</xs:element>

所以最后应该验证以下xml

<example>
    <chunks>...</chunks>
    <filename>...</filename>
    <chunks>...</chunks>
</example>
<!--  -->
<example>
    <filename>...</filename>
    <chunks>...</chunks>
    <chunks>...</chunks>
</example>
<!--  -->
<example>
    <filename>...</filename>
    <chunks>...</chunks>
    <chunks>...</chunks>
    <hostname>...</hostname>
</example>

接受的解决方案:

<xs:element name="example">
    <xs:all>
        <xs:element name="hostname" type="xs:string" minOccurs="0" maxOccurs="1"/>
        <xs:element name="filename" type="xs:string" minOccurs="1" maxOccurs="1"/>
        <xs:element name="chunks" type="xs:string" minOccurs="1" maxOccurs="unbonded"/>
    </xs:all>
</xs:element>

1 个答案:

答案 0 :(得分:1)

可以通过sequencechoice组合重复几种可能组合中的元素来实现这一目标,以保证所需的元素存在,但它赢了& #39;这么好又简单。我会建议一个不同的设计(如果可能的话)。

你的<chunks>元素出现在任何地方有什么原因吗?如果您正在设计XML,那么决定实际需要哪些限制以及哪些限制应该变得灵活,这将简化生成和处理(以及验证)。将它们保存在序列中或包装它们将允许它们被视为group并且将使验证更容易(它还将简化语言映射,例如,包装的相同元素经常被映射为数组)。

保持相似元素在一起的一种形式是sequence,这是您不想要的。另一种方法是将其包装在一个类型中并使用xs:all

<xs:element name="example">
  <xs:complexType>
    <xs:all>
      <xs:element name="filename" type="xs:string" minOccurs="1" maxOccurs="1"/>
      <xs:element name="hostname" type="xs:string" minOccurs="0" maxOccurs="1"/>
      <xs:element name="chunks" type="ChunksType" minOccurs="1" maxOccurs="1"/>
    </xs:all>
  </xs:complexType>
</xs:element>
<xs:complexType name="ChunksType">
  <xs:sequence>
    <xs:element name="chunk" minOccurs="1" maxOccurs="unbounded"/>
  </xs:sequence>
</xs:complexType>

这会验证像这样的XML片段:

<example>
    <chunks>
        <chunk>...</chunk>
        <chunk>...</chunk>
    </chunks>
    <filename>...</filename>
</example>
<!--  -->
<example>
    <filename>...</filename>
    <chunks>
        <chunk>...</chunk>
        <chunk>...</chunk>
    </chunks>
</example>
<!--  -->
<example>
    <filename>...</filename>
    <chunks>
        <chunk>...</chunk>
    </chunks>
    <hostname>...</hostname>
</example>
<example>
    <hostname>...</hostname>
    <filename>...</filename>
    <chunks>
        <chunk>...</chunk>
        <chunk>...</chunk>
    </chunks>
</example>

这些失败了:

<!-- missing filename -->
<example>
    <chunks>
        <chunk>...</chunk>
        <chunk>...</chunk>
    </chunks>
</example>

<!-- no chunks block -->
<example>
    <filename>...</filename>
    <hostname>...</hostname>
</example>

<!-- empty chunks block -->
<example>
    <hostname>...</hostname>
    <filename>...</filename>
    <chunks></chunks>
</example>

您不能将unbounded元素放在xs:all中,因为它只允许01。您不能使用一系列选择,因为您有必需的元素。而且,您无法将xs:allsequence结合起来解决您的问题(实际上您可以执行其中一些操作,但如果您使用的是XSD 1.1)。

XSD 1.1 中,您可以拥有xs:allunbounded元素,因此您可以使用以下方式验证XML:

<xs:all>
    <xs:element name="filename" type="xs:string" minOccurs="1" maxOccurs="1"/>
    <xs:element name="hostname" type="xs:string" minOccurs="0" maxOccurs="1"/>
    <xs:element name="chunks" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
</xs:all>

在XSD 1.0中是非法的。