user305210
user305210

Reputation: 401

XSD - Making an element required inside xs:choice

I am working on an XSD schema where the order of element is not supposed to be enforced. In other words, elements can appear in any order. Some elements are optionals and some are required. As far as I know, xs:sequence is suitable for this kind of situation but since xs:sequence enforces element order, I am only left with xs:choice which is very relaxed when it comes to enforcement. For example, consider an example:

<p>
      <c1>can appear 0 to infinite # of times</c1>
      <c2>must appear exactly once</c2>
      <c1>here the optional element appears again</c1>
</p>

My XSD looks something like this:

<xs:element name="p">
            <xs:complexType>
                         <xs:choice maxOccurs="unbounded">
                                <xs:element name="c1" minOccurs="0" maxOccurs="unbounded" />
                                <xs:element name="c2" minOccurs="1" maxOccurs="1" />
                         </xs:choice>
            </xs:complexType>

However, the above XSD does not enforce that the element "c2" appear exactly once. Element "c2" can be completely absent or can appear more than once and the XML is still considered valid.

Is there really any way I can allow:

Upvotes: 0

Views: 1184

Answers (2)

C. M. Sperberg-McQueen
C. M. Sperberg-McQueen

Reputation: 25034

One of several places this topic has been discussed is this StackOverflow question.

You need a simple regular language over c1 and c2. The automaton you might write has two states: an initial state, in which no c2 has been encountered in the input, and in which c1 and c2 are accepted, and a second state in which c2 has been seen, and in which only c1 is accepted. This language can be described by the regular expression (c1*c2c1*), or by the content model

<xs:sequence>
  <xs:element ref="c1" minOccurs="0" maxOccurs="unbounded"/>
  <xs:element ref="c2"/>
  <xs:element ref="c1" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>

A more general form of the question (with two required elements) is described in this answer to a related SO question. As the number of required elements rises, the content model experiences combinatorial explosion; in those cases, the all-groups of XSD 1.1 are much more convenient.

Upvotes: 1

Michael Kay
Michael Kay

Reputation: 163262

Neither xs:sequence nor xs:choice is suitable for this job. You want xs:all - this allows you to specify a list of elements that can appear in any order. In XSD 1.0 each element can appear zero or one times depending on minOccurs; in XSD 1.1 you can also specify a maxOccurs to allow more than one appearance.

Upvotes: 1

Related Questions