Question

In have the following XML schema (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>

The problem that I'm facing is that this schema allows the Fruits to consist only of the Fruit_id, and I would like to enforce at least one fruit (i.e., Apple or Banana or Cherry or Durian or Elderberry or Fig) to be present in the Fruits. What I tried is to change the above into the following (long story short, replace the sequence with the choice and change the respective minOccurs to 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>

which, indeed, enforces at least one of the aforementioned fruits to exist in the Fruits, but it allows Cherry, Durian, Eldeberry, and Fig, respectively, to appear up to four times in the Fruits, while my intention is that every single one of them, respectively, should be allowed to exist in the Fruits at most once (that's why I tried with maxOccurs="4" in the (nested) choice element).

Was it helpful?

Solution

You have several options, all with some drawbacks.

You can rewrite the nested sequence to require at least one fruit this way:

<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>

(I've omitted the default values of minOccurs and maxOccurs to make the difference between minOccurs="0" and minOccurs="1" stand out more.)

This is dramatically simpler than the corresponding problem when the designer insists on not prescribing an order. But it may still feel kind of bulky.

You could go with your nested-choice design and specify, at the application level, that the only thing that matters is the presence of a given fruit, not the number of times it's present, so <Fruits><Cherry/><Cherry/><Fig/></Fruits> is semantically the same as <Fruits><Cherry/><Fig/></Fruits>. That's not too bad, if in fact they are empty elements, but if they have long complicated contents (and especially if two different instances of Cherry could give different, i.e. conflicting, information), it may seem too dangerous or confusing.

You could add a Schematron layer of validation and add an assertion that Fruits has at least one child (if you stay with your initial sketch) or that Fruit has at most one child of any variety (if you go with the nested-choice approach).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top