Reputation: 2353
I have a root element <a>
and its children <b>, <c>, <d>
Here's what I need:
<b>
<c>
<d>
For example:
<a>
<c />
<b />
<c />
<d />
</a>
And here is my XSD:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="a">
<xs:complexType>
<xs:choice>
<xs:element name="b" />
<xs:element name="c" minOccurs="1" maxOccurs="unbounded"/>
<xs:element name="d" minOccurs="0" maxOccurs="1"/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
But the minOccurs
and maxOccurs
in xs:element
may not work. When I run the example, I got an error:
Element
<b>
is not allowed at this location under element<a>
.
How can I fix this?
Upvotes: 3
Views: 2177
Reputation: 111491
Here's what your XSD says: Within a
you can choose one of the following options:
b
element.c
elements.d
elements.Your XML chooses option #2. It doesn't get a second choice, and when the parser encounters the b
element, it correctly reports the violation.
You might think you could fix this by granting multiple choices:
<xs:choice maxOccurs="unbounded">
This would now say: Within a
you can repeatedly choose one of the following options:
b
element.c
elements.d
elements.Your XML would now choose option #2, then option #1, then option #2, then option #3, then declare that your XML is valid. Success?
No, not if, for example, you wish to ensure only one b
element child because the choice itself is repeated, and option #1 can be repeatedly selected, each time allowing a single b
element, but in aggregate, effectively allowing multiple b
elements.
For this reason, xsd:choice
and, in fact, XSD 1.0 in general cannot be used to represent your constraint.
Your options? Check this constraint in code outside of XSD, or use XSD 1.1's xsd:assert
:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
vc:minVersion="1.1">
<xs:element name="a">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="b" />
<xs:element name="c"/>
<xs:element name="d"/>
</xs:choice>
<xs:assert test="count(b) = 1 and count(c) > 1 and count(d) >= 0"/>
</xs:complexType>
</xs:element>
</xs:schema>
Upvotes: 3