In order to allow an element to appear multiple times but restrict it to element values only being allowed once, I'm applying the unique
element. I've only got it working in an inefficient manner due to the XPath limitations within XSD 1.0 though. 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 the error that "DIGITALARCHIVE" is included twice.
The problem is that this method forces me to include the unique
element in each possible extended Mailpack
type.
So if I e.g. introduce a Parcel
type as an extension of Mailpack
then I have to duplicate the same unique
element from the batch/letter
element in the new batch/parcel
element.
Making the unique
element part of the deliveryMethod
element as below is not an option because the ..
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>
Making it part of the batch
element directly resulted in the same issue.
How can I include the unique
element only once but make it count for all extensions of Mailpack
? (if at all)
By wrapping the
<deliveryMethod>
elements in a (for example)<deliveryMethodsList>
element you can move theunique
element so you only have to write it once.As an example you only need to replace your
Mailpack
complexType with the following:And now you don't need the
unique
element in the letters list:Now the following example is not valid as
<deliveryMethod>DIGITALARCHIVE</deliveryMethod>
appears twice: