如何使用引用约束为无序的XML节点列表创建模式

如何使用引用约束为无序的XML节点列表创建模式,xml,xsd,Xml,Xsd,给定这样的XML布局,我将尝试创建一个XSD模式来验证它 <RootNode> <ChildA /> <ChildC /> <ChildB /> <ChildB /> <ChildA /> </RootNode> 更新:在XSD 1.1m中,所有组上的一些约束已解除。请参阅答案和 这不是一个简单的方案,但似乎可行。这里的难点在于模式定义必须是确定性的。我使用的方法是通过绘制一个有限状态自动机

给定这样的XML布局,我将尝试创建一个XSD模式来验证它

<RootNode>
  <ChildA />
  <ChildC />
  <ChildB />
  <ChildB />
  <ChildA />
</RootNode>

更新:在XSD 1.1m中,所有组上的一些约束已解除。请参阅答案和

这不是一个简单的方案,但似乎可行。这里的难点在于模式定义必须是确定性的。我使用的方法是通过绘制一个有限状态自动机来可视化问题,然后编写一个与该自动机对应的正则表达式。它一点也不像听起来那么复杂。不过,使用其他一些验证系统可能会提供更简单的答案

我做了一些测试,但错过了一些特殊情况是很容易的。如果发现错误,请发表评论

…以下是代码:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" >

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

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

    <xsd:complexType name="ABC">
        <xsd:sequence>
            <xsd:element name="ChildB" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
            <xsd:choice>
                <xsd:sequence maxOccurs="1">
                    <xsd:element name="ChildC" type="xsd:string"/>
                    <xsd:element name="ChildB" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
                    <xsd:element name="ChildA" type="xsd:string"/>
                    <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                        <xsd:element name="ChildA" type="xsd:string" minOccurs="0"/>
                        <xsd:element name="ChildB" type="xsd:string" minOccurs="0"/>
                    </xsd:sequence>
                </xsd:sequence>
                <xsd:sequence maxOccurs="1">
                    <xsd:element name="ChildA" type="xsd:string" minOccurs="1"/>
                    <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                        <xsd:element name="ChildA" type="xsd:string" minOccurs="0"/>
                        <xsd:element name="ChildB" type="xsd:string" minOccurs="0"/>
                    </xsd:sequence>
                    <xsd:sequence minOccurs="0" maxOccurs="1">
                        <xsd:element name="ChildC" type="xsd:string"/>
                        <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                            <xsd:element name="ChildA" type="xsd:string" minOccurs="0"/>
                            <xsd:element name="ChildB" type="xsd:string" minOccurs="0"/>
                        </xsd:sequence>
                    </xsd:sequence>
                </xsd:sequence>
            </xsd:choice>
        </xsd:sequence>
    </xsd:complexType>

</xsd:schema>

我刚才在看报纸

我猜这将在RELAXNG的紧凑语法中浓缩为以下内容:

head = element root { ChildA & ChildC? & ChildB* }

这确实很不错。

这应该符合您的要求:

<xs:element name="RootNode">   
  <xs:complexType>     
    <xs:all>       
      <xs:element name="ChildA" minOccurs="1"/>      
      <xs:element name="ChildB" />       
      <xs:element name="ChildC" minOccurs="0" maxOccurs="1"/>     
    </xs:all>   
  </xs:complexType> 
</xs:element> 


我认为目前的XML模式无法做到这一点。您是否检查过其他验证系统,如RelaxNG(www.RelaxNG.org),在撰写本文时,您可能会提出与此相关的问题,并给出更好的答案:“通过组合和嵌套XML Schema提供的各种组,并通过设置
minOccurs和maxOccurs
的值,可以表示任何可以用XML 1.0 DTD表达的内容模型。”但他们从未说过它会很漂亮。Jasso。这非常聪明。我试图修改它,以提供:无强制元素(丢失ChildA);以及许多0或1发生项目(如ChildC)。我遇到了真正的麻烦。我已将问题发布在。你似乎是这方面的专家。如果你能看一看,我将不胜感激。@Dave感谢你对我的努力表示赞赏。我为你的问题写了一个答案。时间有点晚,因为我已经几个星期没有登录这里了。这个答案非常复杂,但如果你使用XSD 1.0,这是唯一的选择。如果您可以使用
xs:all
做您想做的事情,并且此答案中提到的方法变得不必要的复杂。另请参阅,谢谢您的尝试,但这并不十分合适。A和B可以出现多次,但
元素指定其中的每个元素可能出现零次或仅出现一次。如果有这么简单的解决方案,但我认为jasso的解决方案可能是我们能得到的最好的解决方案。如果为所有子元素设置minOccurs=1和maxOccurs=1,会发生什么?答案是正确的(AFAIKT)如果您使用。解释了XSD 1.0之间允许此操作的差异。
all
不能包含未绑定的子节点。
head=element root{ChildA+&ChildC?&ChildB*}
可能吗?
<xs:element name="RootNode">   
  <xs:complexType>     
    <xs:all>       
      <xs:element name="ChildA" minOccurs="1"/>      
      <xs:element name="ChildB" />       
      <xs:element name="ChildC" minOccurs="0" maxOccurs="1"/>     
    </xs:all>   
  </xs:complexType> 
</xs:element>