so I searched a lot and I cant find any solution. What I need is an XSD that defines that an element must have a specific element as first or last child but can otherwise have an random order of other given elements.
Example:
<a> <!-- Valid -->
<b />
<c1 />
<c2 />
<c3 />
</a>
<a> <!-- Valid -->
<c2 />
<c1 />
<c3 />
<b />
</a>
<a> <!-- Invalid -->
<c2 />
<b />
<c1 />
<c3 />
</a>
So basically I am trying to create an XSD that allowes c1,c2,c3 in random order and in random quantity but always must have one b either at the top or the bottom.
I know about xsd:all and xsd:sequence but I can't find anything that would fit my problem.
CodePudding user response:
With XSD 1.1 xs:all
using an xs:assert
:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="a" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name="b" minOccurs="0" maxOccurs="1"/>
<xs:element name="c1"/>
<xs:element name="c2"/>
<xs:element name="c3"/>
</xs:all>
<xs:assert id="b-is-first-or-last-child"
test="*[1] instance of element(b) or *[last()] instance of element(b)"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
both Saxon-EE as well as Xerces flag the last a
as invalid:
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="schema2.xsd">
<a> <!-- Valid -->
<b />
<c1 />
<c2 />
<c3 />
</a>
<a> <!-- Valid -->
<c2 />
<c1 />
<c3 />
<b />
</a>
<a> <!-- Invalid -->
<c2 />
<b />
<c1 />
<c3 />
</a>
</root>
CodePudding user response:
I was able to solve this problem using a group element sequence.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:group name="children">
<xs:choice>
<xs:element name="c1" />
<xs:element name="c2" />
<xs:element name="c3" />
</xs:choice>
</xs:group>
<xs:complexType name="aNode">
<xs:choice>
<xs:sequence>
<xs:element name="b" minOccurs="1" maxOccurs="1" />
<xs:group ref="children" minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
<xs:sequence>
<xs:group ref="children" minOccurs="1" maxOccurs="unbounded" />
<xs:element name="b" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:choice>
</xs:complexType>
<xs:complexType name="rootNode">
<xs:sequence>
<xs:element name="a" type="aNode" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:element name="root" type="rootNode" />
</xs:schema>