How to declare special XML schema (XSD) case
Question
I need your help to define a special case in XML schema: A sequence that contains two elements: 'x' and 'y' whereas:
<x>
element can appear 0 to unbound times in the sequence<y>
element can appear 0 to 1 time in the sequence<x>
and<y>
locations can be anywhere - that is, it is possible to have unbound times the<x>
element and then a single<y>
element, and then unbound times the<x>
element.
XML examples of this problem:
Example #1
<x>stuff</x>
<y>stuff</y>
<x>stuff</x>
Example #2
<y>stuff</y>
<x>stuff</x>
<x>stuff</x>
Example #3
<x>stuff</x>
<x>stuff</x>
<y>stuff</y>
<x>stuff</x>
Thanks!
Solution
For various reasons, none of Yuval's, Mo's or davidsheldon's samples work. Here's one that does.
<xs:complexType name="myComplexType">
<xs:sequence>
<xs:element name="x" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:sequence minOccurs="0">
<xs:element name="y" type="xs:string"/>
<xs:element name="x" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:sequence>
</xs:complexType>
OTHER TIPS
EDIT: As Alohci mentioned, my solution is incorrect. According to the spec, an element in xs:all can only appear zero or one time. Sorry for any inconvenience
I think what you want isn't a sequence. A sequence defines not only the elements but also the order. And in your case the order may change. Have you tried xs:all?
<xs:complexType name="myComplexType">
<xs:all>
<xs:element name="x" type="xs:string" maxOccurs="unbounded"/>
<xs:element name="y" type="xs:string" maxOccurs="1"/>
</xs:all>
</xs:complexType>
Another appraoch might be to make it a sequence but mark the sequence to be maxOccurs="unbounded"
It has been a while since I used schema, but I think sequences are your answer here.
You need to have an unbounded number of choices between (an x), or (a y followed by an x).
<xsd:element name="parent">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="x" type="xs:string"/>
<xsd:sequence>
<xsd:element name="y" type="xsd:string" />
<xsd:element name="x" type="xsd:string" />
</xsd:sequence>
</xsd:choice>
</xsd:complexType>
</xsd:element>
Not too complicated. Off the top of my head, it should be something like this:
<xs:element name="x" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="y" type="xs:string" minOccurs="0" maxOccurs="1"/>
<xs:element name="x" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
Since each element in XSD is optional by default, this XSD will match the XML structure you have defined, with the y
element appearing anywhere before, after or between the x
elements, with a maximum occurence of 1