XSD中的互斥元素

时间:2016-06-01 05:03:19

标签: xsd xsd-validation

我想实现一种关系,其中" Rate"元素应仅存在于" ComponentInstId和" ComponentInstIdServ"不存在,反之亦然。我怎么能在下面的xsd代码中做到这一点?

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="Request">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="Component">
                <xs:complexType>
                    <xs:all>
                        <xs:element name="ComponentId" nillable="false">
                            <xs:simpleType>
                                <xs:restriction base="xs:integer">
                                    <xs:whiteSpace value="collapse"/>
                                </xs:restriction>
                            </xs:simpleType>
                        </xs:element>
                        <xs:element name="ComponentInstId" nillable="true" minOccurs="0">
                            <xs:simpleType>
                                <xs:restriction base="xs:integer">
                                    <xs:whiteSpace value="collapse"/>
                                </xs:restriction>
                            </xs:simpleType>
                        </xs:element>
                        <xs:element name="ComponentInstIdServ" nillable="true" minOccurs="0">
                            <xs:simpleType>
                                <xs:restriction base="xs:int">
                                    <xs:whiteSpace value="collapse"/>
                                </xs:restriction>
                            </xs:simpleType>
                        </xs:element>
                        <xs:element name="Rate" nillable="true" minOccurs="0">
                            <xs:simpleType>
                                <xs:restriction base="xs:int">
                                    <xs:whiteSpace value="collapse"/>
                                    <xs:minInclusive value="0"/>
                                </xs:restriction>
                            </xs:simpleType>
                        </xs:element>
                    </xs:all>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:element>

1 个答案:

答案 0 :(得分:2)

为什么不等同于(ComponentId, (Rate | (ComponentInstId, ComponentInstIdServ?)?))

允许订单变化有多重要?儿童的顺序是否提供了有用的信息?如果没有,请修复序列,就像HTML要求headbody之前而不是之后。如果序列确实提供了信息,您可以将可能性相乘,或者重构XML。如果将ComponentId作为Component上的必需属性,以及ComponentInst上的Id和IdServ属性,那么Component的内容模型可以只是(Rate | ComponentInst)?

你说&#34;顺序并不重要。&#34;如果这意味着&#34;序列不传达任何信息&#34;,则以下形式的声明可确保您始终拥有组件的Id以及Rate信息或ComponentInst信息,或两者都没有。

<xs:element name="Component">
  <xs:complexType>
    <xs:choice minOccurs="0">
      <xs:element name="Rate" nillable="true">
        <xs:simpleType>
          <xs:restriction base="xs:int">
            <xs:whiteSpace value="collapse"/>
            <xs:minInclusive value="0"/>
          </xs:restriction>
        </xs:simpleType>
      </
      <xs:element name="ComponentInst" nillable="true">
        <xs:complexType>
         <xs:sequence/>
         <xs:attribute name="Id" type="xs:int"/>
         <xs:attribute name="IdServ" type="xs:nonNegativeInteger"/>
        </
      </
    </
    <xs:attribute name="Id" type="xs:int" use="required"/>
  </
</

(未经测试,因为缺少完整的末端标签是建议的。)

如果&#34;序列并不重要&#34;你的意思是&#34;所有可能的信息序列都必须是有效的,然后你的内容模型需要更复杂,但它足够简单的正则表达式来解决。

[附录]由于Stack Overflow的一些读者显然无法解决这样的问题,但是,这里有一个允许元素A(思考:ComponentId),B(思考:速率),C(ComponentInstId)和D(ComponentInstIdServ)以任何顺序出现,其中A是必需的,其他是可选的,并且具有约束,即如果B既不发生C也不发生D.

首先,让我们以DTD或Relax NG紧凑语法的紧凑表示法写出所有可能序列的选择:

( (A, B?)
| (A, C?, D?)
| (A, D?, C?)
| (B?, A)
| (C?, A, D?)
| (C?, D, A)
| (D?, A, C?)
| (D?, C, A)
)

然而,由于“独特的粒子归因”,这个(或者更确切地说是它的XSD等效物)并不合法。 XSD规则,因此我们需要分解各种左手前缀,并且通常使表达式具有确定性。一个实例可以从A,B,C或D开始,因此首先我们为这些情况制作四个确定性表达式,然后我们可以将它们放在一个选择中。如果A是第一个:

( A, ( (B) | (C, D?) | (D, C?) )? )

如果B是第一个:

(B, A?)

如果C是第一个:

(C ( (A, D?) | (D, A) ) )

如果D是第一个:

(D ( (A, C?) | (C, A) ) )

或者,现在一起:

( ( A, ( (B) | (C, D?) | (D, C?) )? )
| (B, A?)
| (C ( (A, D?) | (D, A) ) )
| (D ( (A, C?) | (C, A) ) )
)

或者,在XSD等价物中:

<xs:complexType name="demo">
  <xs:choice>
    <!--* we can start with A *-->
    <xs:sequence>
      <xs:element ref="A"/>
      <xs:choice minOccurs="0">
        <xs:element ref="B" minOccurs="0"/>
        <xs:sequence>
          <xs:element ref="C"/>
          <xs:element ref="D" minOccurs="0"/>
        </xs:sequence>
        <xs:sequence>
          <xs:element ref="D"/>
          <xs:element ref="C" minOccurs="0"/>
        </xs:sequence>
      </xs:choice>
    </xs:sequence>
    <!--* or we can start with B *-->
    <xs:sequence>
      <xs:element ref="B"/>
      <xs:element ref="A" minOccurs="0"/>
    </xs:sequence>
    <!--* or we can start with C *-->
    <xs:sequence>
      <xs:element ref="C"/>
      <xs:choice>
        <xs:sequence>
          <xs:element ref="A"/>
          <xs:element ref="D" minOccurs="0"/>
        </xs:sequence>
        <xs:sequence>
          <xs:element ref="D"/>
          <xs:element ref="A"/>
        </xs:sequence>
      </xs:choice>
    </xs:sequence>
    <!--* or we can start with D *-->
    <xs:sequence>
      <xs:element ref="D"/>
      <xs:choice>
        <xs:sequence>
          <xs:element ref="A"/>
          <xs:element ref="C" minOccurs="0"/>
        </xs:sequence>
        <xs:sequence>
          <xs:element ref="C"/>
          <xs:element ref="A"/>
        </xs:sequence>
      </xs:choice>
    </xs:sequence>
  </xs:choice>
</xs:complexType>