XML模式强制存在元素

时间:2014-05-07 13:49:04

标签: xml xsd xsd-1.0

具有以下XML架构(XSD 1.0):

<xs:element name="Fruits">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="Fruit_id" type="xs:int" minOccurs="1" maxOccurs="1"/>
      <xs:choice minOccurs="1" maxOccurs="1">
        <xs:element ref="Apple" minOccurs="1" maxOccurs="1"/>
        <xs:element ref="Banana" minOccurs="1" maxOccurs="1"/>
        <xs:sequence>
          <xs:element ref="Cherry" minOccurs="0" maxOccurs="1"/>
          <xs:element ref="Durian" minOccurs="0" maxOccurs="1"/>
          <xs:element ref="Elderberry" minOccurs="0" maxOccurs="1"/>
          <xs:element ref="Fig" minOccurs="0" maxOccurs="1"/>
        </xs:sequence>
      </xs:choice>
    </xs:sequence>
  </xs:complexType>
</xs:element>

我遇到的问题是这个架构允许Fruits只包含Fruit_id,我想强制执行至少一个水果(即AppleBananaCherryDurianElderberryFig)出现在Fruits中。我尝试将以上内容更改为以下内容(长话短说,将sequence替换为choice并将相应的minOccurs更改为1):

<xs:element name="Fruits">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="Fruit_id" type="xs:int" minOccurs="1" maxOccurs="1"/>
      <xs:choice minOccurs="1" maxOccurs="1">
        <xs:element ref="Apple" minOccurs="1" maxOccurs="1"/>
        <xs:element ref="Banana" minOccurs="1" maxOccurs="1"/>
        <xs:choice minOccurs="1" maxOccurs="4">
          <xs:element ref="Cherry" minOccurs="1" maxOccurs="1"/>
          <xs:element ref="Durian" minOccurs="1" maxOccurs="1"/>
          <xs:element ref="Elderberry" minOccurs="1" maxOccurs="1"/>
          <xs:element ref="Fig" minOccurs="1" maxOccurs="1"/>
        </xs:choice>
      </xs:choice>
    </xs:sequence>
  </xs:complexType>
</xs:element>
实际上,

实施Fruits中至少有一个上述水果,但它允许CherryDurianEldeberry和{{1分别在Fig中出现最多四次,而我的目的是分别允许它们中的每一个分别至少存在Fruits一次(这就是为什么我在(嵌套的)Fruits元素中尝试使用maxOccurs="4"

1 个答案:

答案 0 :(得分:2)

你有几个选择,都有一些缺点。

您可以通过这种方式重写嵌套序列以至少需要一个水果:

<xs:choice>
  <xs:sequence>
    <xs:element ref="Cherry"/>
    <xs:element ref="Durian" minOccurs="0"/>
    <xs:element ref="Elderberry" minOccurs="0"/>
    <xs:element ref="Fig" minOccurs="0"/>
  </xs:sequence>        
  <xs:sequence>
    <xs:element ref="Durian"/>
    <xs:element ref="Elderberry" minOccurs="0"/>
    <xs:element ref="Fig" minOccurs="0"/>
  </xs:sequence>        
  <xs:sequence>
    <xs:element ref="Elderberry"/>
    <xs:element ref="Fig" minOccurs="0"/>
  </xs:sequence>        
  <xs:sequence>
    <xs:element ref="Fig"/>
  </xs:sequence>    
</xs:choice>

(我省略了minOccurs和maxOccurs的默认值,以区分minOccurs =&#34; 0&#34;而minOccurs =&#34; 1&#34;更突出。)

当设计师坚持不开具订单时,这比相应的问题简单得多。但它可能仍然感觉有点笨重。

您可以使用嵌套选择设计,并在应用程序级别指定唯一重要的是给定水果的存在,而不是它存在的次数,所以{{1在语义上与<Fruits><Cherry/><Cherry/><Fig/></Fruits>相同。这不是太糟糕,如果事实上它们是空的元素,但如果它们有很长的复杂内容(特别是如果两个不同的Cherry实例可以提供不同的,即冲突的信息),它可能看起来太危险或令人困惑

您可以添加一个Schematron验证层,并添加一个断言,其中Fruit至少有一个孩子(如果您保留初始草图)或者Fruit最多有一个任何种类的孩子(如果您使用嵌套的 - 选择方法)。