如何为无序列表创建一个模式,其中一些模式出现一次,多次出现

时间:2013-01-14 15:38:56

标签: xsd

这是与How to create a schema for an unordered list of XML nodes, with occurrence constraints类似的问题,但实际上稍微简单一些。然而,我很难理解序列和选择背后的逻辑(特别是当它们嵌套到选择序列或序列选择中时),虽然我已经研究了很长时间但我无法理解上面的例子的工作原理。

我需要的是节点列表的模式,ChildA和ChildB,其中ChildA可以出现0-n次,但ChildB只出现0-1次。 (实际上我需要每种类型的几个节点,但是如果我可以为ChildA和ChildB做,将它扩展到ChildX等,而ChildY等应该很简单)。应该没有订单限制。我很感激任何帮助。任何深入解释模式指标的链接也会有所帮助。

3 个答案:

答案 0 :(得分:4)

这将是我最快想到的最简单的解决方案。这里的关键是在“主”序列中使用另一个序列。通过将内部序列设置为以<ChildB>开头来保持模式的确定性,并通过将该序列的基数设置为0-1来保持<ChildB>是可选的。

这是一个XMLSchema 1.0解决方案。

<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <!-- Schema for elements ChildA and ChildB
      The requirements are as follows:
          * ChildA and ChildB may occur in any order.
          * ChildA is optional and may occur multiple times.
          * ChildB is optional and may occur once only.
  -->

  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" name="AB-container" type="AB-type" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="AB-type">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="ChildA" type="xs:string" />
      <xs:sequence minOccurs="0">
        <xs:element name="ChildB" type="xs:string" />
        <xs:element minOccurs="0" maxOccurs="unbounded" name="ChildA" type="xs:string" />
      </xs:sequence>
    </xs:sequence>
  </xs:complexType>

</xs:schema>

答案 1 :(得分:1)

简短的回答是它无法在XSD 1.0中完成;在XSD 1.1你可以使用一个xsd:all合成(因为限制从XSD 1.0唯一的maxOccurs = 1已经被移除具有) - 然而,XSD 1.1的问题是,i)其仅可自由地作为测试版Xerces版本 - 据我所知,此时; ii)有一个SAXON版本支持它,上次我看到它的引用你必须支付它和iii)你将很难与其他人互操作,因为大多数仍然在XSD 1.0上。

如果你可以使用Schematron - 肯定比XSD 1.1更容易访问,因为它只是XSLT 1.0 / 2.0,那么它应该很容易编码,以便特定元素粒子的数量符合指定的标准;它会增加一个XSD,其中合成器将是一个重复xsd:choice,其中选项选项是您允许的集合中的元素。

有些人试图通过与正则表达式的构造并行来解释XSD合成器。如果你熟悉它,那么XSD 1.0中的xsd:all类似于方括号(虽然更简单,没有范围或否定的概念),xsd:choice就像| (管道,交替)和xsd:sequence是其余的(你写东西的顺序很重要)。

我看到SO上的其他人推荐W3Schools。我自己没有尝试过,所以我用免责声明传递给你。

答案 2 :(得分:0)

@Dave正在为ChildB添加一些哑属性好吗?由于您对childB的要求是0-1,我们可以通过向childB添加固定属性并对属性强制执行唯一约束来实现所需的解决方案。

<complexType name="childAType">
 <simpleContent>
   <extension base="string"></extension>
 </simpleContent>
</complexType>


<complexType name="childBType">
 <simpleContent>
   <extension base="string">
     <attribute name="value" type="string" fixed="123"></attribute>
   </extension>
 </simpleContent>
</complexType>


<element name="root">
 <complexType>
   <choice minOccurs="0" maxOccurs="unbounded">
        <element name="childA" type="tns:childAType" minOccurs="0" maxOccurs="unbounded"></element>
        <element name="childB" type="tns:childBType" minOccurs="0" maxOccurs="unbounded"></element>
   </choice>
 </complexType>
 <unique name="childB.max.once">
   <selector xpath="./tns:childB"></selector>
   <field xpath="@value"></field>
 </unique>
</element>

以下是有效的XML之一(B的顺序无关紧要或B可以排除)

<tns:root xmlns:tns=" ">
 <tns:childA></tns:childA>
 <tns:childB></tns:childB>
 <tns:childA></tns:childA>
 <tns:childA></tns:childA>
</tns:root>

但是下面的内容无效

<tns:root xmlns:tns=" ">
 <tns:childB></tns:childB>
 <tns:childA></tns:childA>
 <tns:childB></tns:childB>
 <tns:childA></tns:childA>
 <tns:childA></tns:childA>
</tns:root>