Is it possible in W3C's XML Schema language (XSD) to allow a series of elements to be in any order but still limit occurrences?
Question
I know about all
and choice
, but they don't account for a case where I do want some elements to be able to occur more than once, such as:
<Root>
<ThingA/>
<ThingB/>
<ThingC/>
<ThingC/>
<ThingC/>
</Root>
I could use sequence
, but I'd prefer to allow these children to be in any order. I could use any
, but then I couldn't have more than one ThingC
. I could use choice
, but then I couldn't limit ThingA
and ThingB
to 0 or 1.
I think I may have read somewhere that this was either difficult or impossible in XSD, but might be possible with RELAX NG. I don't remember where I read that, unfortunately.
Thanks for any help!
Solution
That's right: you can't do what you want to do in XML Schema, but you can in RELAX NG with:
<element name="Root">
<interleave>
<element name="ThingA"><empty /></element>
<element name="ThingB"><empty /></element>
<oneOrMore><element name="ThingC"><empty /></element></oneOrMore>
</interleave>
</element>
Your options in XML Schema are:
- add a preprocessing step that normalises your input XML into a particular order, and then use
<xs:sequence>
- use
<xs:choice>
, and add extra validation (for example using Schematron) to check that there's not more than one<ThingA>
or<ThingB>
- decide to fix the order of the elements in your markup language
It turns out that the third is usually the best option; there's usually not much cost for generators of XML to output elements in a particular order, and not only does it help validation but it also aids consumption of the XML if the order can be known in advance.