这是与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等应该很简单)。应该没有订单限制。我很感激任何帮助。任何深入解释模式指标的链接也会有所帮助。
答案 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>