XSD unique XPath constraint element
To allow an element to appear multiple times, but restrict it to values ββallowed only once, I am using an element unique
. I only worked, working inefficiently, due to XPath limitations in XSD 1.0. XSD 1.1 is unfortunately not an option for me.
Below is a simplified version of the XSD:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:simpleType name="DeliveryMethod">
<xs:restriction base="xs:string">
<xs:enumeration value="POST"/>
<xs:enumeration value="DIGITALARCHIVE"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="Mailpack">
<xs:sequence>
<xs:element maxOccurs="unbounded" name="deliveryMethod" type="DeliveryMethod"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Letter">
<xs:complexContent>
<xs:extension base="Mailpack">
<xs:sequence>
<xs:element name="content" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="batch">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="id" type="xs:string"/>
<xs:choice>
<xs:element maxOccurs="unbounded" name="letter" type="Letter">
<xs:unique name="oneOfEachDeliveryMethodType">
<xs:selector xpath="deliveryMethod"/>
<xs:field xpath="." />
</xs:unique>
</xs:element>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
With the following XML:
<?xml version="1.0" encoding="utf-8"?>
<batch>
<id>123</id>
<letter>
<deliveryMethod>POST</deliveryMethod>
<deliveryMethod>DIGITALARCHIVE</deliveryMethod>
<deliveryMethod>DIGITALARCHIVE</deliveryMethod>
<content>Narf!</content>
</letter>
</batch>
This works as expected and gives me an error that "DIGITALARCHIVE" is included twice. The problem is that this method forces me to include an element unique
in every possible extended type Mailpack
. So if I, for example. put type Parcel
as extension Mailpack
then i have to duplicate same element unique
from element batch/letter
in new element batch/parcel
.
Creating an element element unique
element deliveryMethod
as shown below is not an option because parent selector is ..
not allowed in XSD XPath.
<xs:complexType name="Mailpack">
<xs:sequence>
<xs:element maxOccurs="unbounded" name="deliveryMethod" type="DeliveryMethod">
<xs:unique name="oneOfEachDeliveryMethodType">
<xs:selector xpath="deliveryMethod"/>
<xs:field xpath=".." />
</xs:unique>
</xs:element>
</xs:sequence>
</xs:complexType>
Casting it to an element batch
directly led to the same problem.
How to include an element unique
only once, but count the number of all extensions Mailpack
? (if at all)
source to share
By wrapping elements <deliveryMethod>
in an element (for example) <deliveryMethodsList>
you can move the element around unique
, so you only need to write it once.
As an example, you need to replace your Mailpack
complexType with the following:
<xs:complexType name="Mailpack">
<xs:sequence>
<xs:element name="deliveryMethodsList">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="deliveryMethod" type="DeliveryMethod"/>
</xs:sequence>
</xs:complexType>
<!-- Unique is only placed here -->
<xs:unique name="oneOfEachDeliveryMethodType">
<xs:selector xpath="deliveryMethod"/>
<xs:field xpath="." />
</xs:unique>
</xs:element>
</xs:sequence>
</xs:complexType>
And now you don't need an item unique
in the list of letters:
<xs:element maxOccurs="unbounded" name="letter" type="Letter" />
Now the following example is invalid because it <deliveryMethod>DIGITALARCHIVE</deliveryMethod>
appears twice:
<?xml version="1.0" encoding="utf-8"?>
<batch>
<id>123</id>
<letter>
<deliveryMethodsList>
<deliveryMethod>POST</deliveryMethod>
<deliveryMethod>DIGITALARCHIVE</deliveryMethod>
<deliveryMethod>DIGITALARCHIVE</deliveryMethod>
</deliveryMethodsList>
<content>Narf!</content>
</letter>
</batch>
source to share