3

This is a similar question to How to create a schema for an unordered list of XML nodes, with occurrence constraints, but actually slightly simpler. However I am having great trouble understanding the logic behind sequences and choices (and especially when they are nested into sequences of choices or choices of sequences), and although I've studied it for a long time I can't understand how the example above works.

What I need is schema for a list of nodes, ChildA and ChildB, whereby ChildA can occur 0-n times, but ChildB only 0-1 times. (Actually I need several nodes of each type, but if I can do it for ChildA and ChildB, extending it to ChildX etc. and ChildY etc. should be simple). There should be no order constraint. I'd appreciate any help. Any links that explain schema indicators in depth would also be helpful.

4

3 回答 3

3

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

这是一个 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>
于 2013-02-12T23:44:49.203 回答
1

简短的回答是它不能在 XSD 1.0 中完成。在 XSD 1.1 中,您可以使用xsd:all合成器(因为 XSD 1.0 中只有 maxOccurs = 1 的限制已被删除) - 但是, XSD 1.1 的问题是 i)它只能作为 beta Xerces 版本免费提供 - 到目前为止据我所知,在这个时候;ii) 有一个 SAXON 版本支持它,上次我看到对它的引用时,您必须为此付费,并且 iii) 您将很难与其他人进行互操作,因为他们中的大多数人仍在 XSD 1.0 上。

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

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

我看到 SO 上的其他人推荐W3Schools。我自己没有尝试过,因此我将其与免责声明一起传递给您。

于 2013-01-14T20:03:41.780 回答
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>
于 2013-01-15T08:57:42.073 回答