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)

+3


source to share


1 answer


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>

      

+2


source







All Articles