Is it valid to have a 'choice' of 'group' elements when defining an XML Schema (XSD)

Vihung picture Vihung · Sep 19, 2008 · Viewed 11.2k times · Source

Is it valid to have a 'choice' or 'group' elements when defining an XML Schema (XSD)

i.e. is the following valid

<xs:complexType name="HeaderType">
  <xs:sequence>
    <xs:element name="reservation-number" type="ReservationNumberType" minOccurs="1" maxOccurs="1" nillable="false" />
    <xs:choice minOccurs="1" maxOccurs="1">
      <xs:group ref="ReservationGroup" />
      <xs:group ref="CancellationGroup"/>
    </xs:choice>
  </xs:sequence>
</xs:complexType>

Where an XML message can represent, for example, either a new reservation or a cancellation of an existing reservation.

If the message is for a reservation, then it must include all the elements defined in the ReservationGroup group.

If it is a cancellation, then it must include all the elements defined in the CancellationGroup group.

For some reason, my XML editor (Eclipse) does not like this, but does not indicate why. It shows there being an error on the line <xs:complexType name="HeaderType"> but does not say what the error is

Answer

Dunderklumpen picture Dunderklumpen · Sep 19, 2008

I'm no XML expert, although I use it quite a lot. This isn't the way I'd generally do this sort of structure. I would prefer a separate complex types rather than a choice of two groups (see the very end of this answer).

I suspect that the problem is that ReservationGroup and CancellationGroup start with the same element, in which case you will violate the Schema Component Constraint: Unique Particle Attribution (below).

http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/#cos-nonambig

Schema Component Constraint: Unique Particle Attribution

A content model must be formed such that during ·validation· of an element information item sequence, the particle component contained directly, indirectly or ·implicitly· therein with which to attempt to ·validate· each item in the sequence in turn can be uniquely determined without examining the content or attributes of that item, and without any information about the items in the remainder of the sequence.

Note: This constraint reconstructs for XML Schema the equivalent constraints of [XML 1.0 (Second Edition)] and SGML. Given the presence of element substitution groups and wildcards, the concise expression of this constraint is difficult, see Analysis of the Unique Particle Attribution Constraint (non-normative) (§H) for further discussion.

For example, the two groups below are illegal in the same choice, because each of their first element is "name" which means that you cannot identify which group you are looking at. However is the first element of ReservationGroup is different from Cancellation group (resDate and cancDate maybe), then the that is valid.

Edit: I'd never come across this sort of problem before, and I think its fascinating that the definitions of the groups are totally legal, but if you put them together in a choice, that choice becomes illegal because of the definition of each group.

Groups that cannot form a legal choice

<xs:group name="ReservationGroup">
    <xs:sequence>
        <xs:element name="date"/>
        <xs:element name="name"/>
        <xs:element name="address"/>
    </xs:sequence>
</xs:group>

<xs:group name="CancellationGroup">
    <xs:sequence>
        <xs:element name="date"/>
        <xs:element name="name"/>
        <xs:element name="address"/>
    </xs:sequence>
</xs:group>

Groups that can form a legal choice

<xs:group name="ReservationGroup">
    <xs:sequence>
        <xs:element name="resDate"/>
        <xs:element name="name"/>
        <xs:element name="address"/>
    </xs:sequence>
</xs:group>

<xs:group name="CancellationGroup">
    <xs:sequence>
        <xs:element name="cancDate"/>
        <xs:element name="name"/>
        <xs:element name="address"/>
    </xs:sequence>
</xs:group>

As I mentioned above, I'd do this sort of thing with complex types. Yes, it adds another element, but it seems the obvious way and I like obviousness.

<xs:complexType name="HeaderType">
  <xs:sequence>
    <xs:element name="reservation-number" type="ReservationNumberType" minOccurs="1" maxOccurs="1" nillable="false" />
    <xs:choice minOccurs="1" maxOccurs="1">
      <xs:element name="reservation" type="ReservationType" />
      <xs:element name="cancellation" type="CancellationType" />
    </xs:choice>
  </xs:sequence>
</xs:complexType>