XML Schema中的嵌套选择元素?

时间:2014-04-18 07:16:46

标签: xml schema xsd xsd-validation

我要做的是,声明一个名为“data”的父元素,它具有这两个元素的6个子元素是条件的,这意味着如果选择元素A则B不会出现在“数据”中。

像这样:

<data>
   <A>text1</A>
   <B>text1</B>
   <C>text1</C>
   <D>text1</D>

   <E>text1</E> or <F>text1</F>

</data>

要求1:所有元素都可以按任意顺序和任意次数出现。

要求2:元素E&amp; F是条件均值,其中只有一个是数据中的apear。

我的xsd代码是这样的:

<xs:element name="data">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="sequence" minOccurs="0" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:choice minOccurs="0" maxOccurs="unbounded" >
                            <xs:element ref="A" />
                            <xs:element ref="B" />
                            <xs:element ref="C" />
                            <xs:element ref="D" />                          
                            <xs:choice>
                                <xs:element ref="E" />
                                <xs:element ref="F" />
                                <xs:element ref="G" />
                            </xs:choice>
                        </xs:choice>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
            <xs:attribute name="status"/>
        </xs:complexType>
    </xs:element>

我已经尝试了所有这些链接,但仍然没有得到我的解决方案。

XSD - how to allow elements in any order any number of times?

Nested sequence in XSD

XSD nested element

2 个答案:

答案 0 :(得分:3)

你的内容模型已经被各种各样称为“歧义规则”(在SGML中),“确定性规则”(在XML中称为,它拒绝称之为歧义规则,因为事实上是禁止的)实际上并不是模糊性,而是从内容模型中以特定方式形成的有限状态自动机的非确定性,或“独特的粒子归因规则”(因为XSD 1.0的主编编辑似乎认为它们是不同的在某种程度上,从XML的确定性规则;我忘记了应该是什么区别,只记得它是基于对XML规则的误解)。它们实际上并没有很好的技术动机(它们是SGML中的设计错误,出于兼容性原因而被转移到XML中,并且完全没有任何理由进入XSD),并且(正如您所发现的那样)它们使法律结构复杂化内容模型,这是一些人对Relax NG感到满意的一个原因,它们主要消除它们。但是,无论好坏,它们都是XML文档语法的众多语言的一部分,因此值得了解如何遵守它们。

您描述的语言是:A,B,C或D元素的任何序列, 与E元素或F元素混合。要在确定性内容模型中描述此语言,您可能会发现有必要考虑自动机必须具有的不同状态,以便识别这种语言。在一种状态下,元素A至F中的任何一个都是合法的。元素A到D让我们处于那种状态。但是一旦我们看到E或F,我们会进入一个不同的状态,其中A到D以及E或F(无论我们先看到哪个)是合法的,但是另一个(F或E)是不被接受的。所以我们需要三个州。

请注意,每个状态都对应于它自己的语言:我们可以看到的元素序列将我们置于该状态并使我们处于该状态。如果我们将状态命名为initialeeeeff,我们可以使用正则表达式对语言进行汇总,这些表达式很容易转换为XSD:

  • L(初始)=(A | B | C | D)*
  • L(eee)= E,(A | B | C | D | E)*
  • L(eff)= F,(A | B | C | D | F)*

请注意,从第一个状态开始,我们可以移动到第二个或第三个状态,但是一旦我们处于这两个状态中,我们就永远不会离开它。这意味着我们想要的语言实际上是L(初始),然后选择L(eee)或L(eff)。因此,一个XSD公式将是:

<xsd:group name="initial">
  <xsd:sequence>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="A"/>
      <xsd:element ref="B"/>
      <xsd:element ref="C"/>
      <xsd:element ref="D"/>
    </xsd:choice>      
  </xsd:sequence>    
</xsd:group>
<xsd:group name="eee">
  <xsd:sequence>
    <xsd:sequence minOccurs="0">
      <xsd:element ref="E"/>
      <xsd:choice minOccurs="0" maxOccurs="unbounded">
        <xsd:element ref="A"/>
        <xsd:element ref="B"/>
        <xsd:element ref="C"/>
        <xsd:element ref="D"/>
        <xsd:element ref="E"/>
      </xsd:choice>
    </xsd:sequence>
  </xsd:sequence>    
</xsd:group>
<xsd:group name="eff">
  <xsd:sequence minOccurs="0">
    <xsd:element ref="F"/>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="A"/>
      <xsd:element ref="B"/>
      <xsd:element ref="C"/>
      <xsd:element ref="D"/>
      <xsd:element ref="F"/>
    </xsd:choice>
  </xsd:sequence>
</xsd:group>
<xsd:complexType name="data">
  <xsd:sequence>
    <xsd:group ref="initial"/>
    <xsd:choice>
      <xsd:group ref="eee"/>
      <xsd:group ref="eff"/>
    </xsd:choice>
  </xsd:sequence>
</xsd:complexType>
<xsd:element name="data" type="data"/>

这相当于以不同的方式描述您的语言:A,B,C或D元素的序列,可选地依次为E,然后是A,B,C,D或E元素的任何序列,或者由F,然后是A,B,C,D或F元素的任何序列。值得花费尽可能多的时间来说服自己所描述的语言与您在问题描述中描述的语言相同。

答案 1 :(得分:0)

因此可以在(A|B|C|D|E)*(A|B|C|D|F)*之间进行选择 - 您可以将常见A|B|C|D部分分解为group

<xs:group name="commonElements">
  <xs:choice>
    <xs:element ref="A" />
    <xs:element ref="B" />
    <xs:element ref="C" />
    <xs:element ref="D" />
  </xs:choice>
</xs:group>

<xs:element name="data">
  <xs:complexType>
    <xs:choice>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:group ref="commonElements" />
        <xs:element ref="E" />
      </xs:choice>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:group ref="commonElements" />
        <xs:element ref="F" />
      </xs:choice>
    </xs:choice>
  </xs:complexType>
</xs:element>

这将允许任何顺序的A,B,C,D,E,F的任何混合,但如果有F则不允许任何Es,反之亦然。