PowderFan
PowderFan

Reputation: 98

XSD to validate unique id attribute within a parent for n-th child

I have a rather unusual problem it seems. I have an xml that looks roughly something liket his:

<?xml version="1.0" encoding="utf-8"?>
<root xmlns="tbd">
    <A>
        <B id="01">
            <C id="02" />
            <C id="03" />
        </B>
        <B id="04">
            <C id="05" />
        </B>
    </A>
    <A>
        <B id="01">
            <C id="02" />
            <C id="03" />
        </B>
        <B id="04">
            <C id="05" />
        </B>
    </A>
</root>

As you can see, the block A can repeat n times. My problem is validating that the id attribute is unique for all decendents of A (child, grandchild, asf.). So far I managed to validate that the id of B is unique inside of A, and that the id of C is unique inside of B with am XSD that looks something like this:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="tbd" xmlns:tbd="tbd" elementFormDefault="qualified">
    <xs:element name="root">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="A" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="B" maxOccurs="unbounded">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="C" maxOccurs="unbounded">
                                            <xs:ComplexType>
                                                <xs:attribute name="id" type="xs:int" use="required" />
                                            </xs:complexType>
                                        </xs:element>
                                    </xs:sequence>
                                </xs:complexType>
                                <xs:attribute name="id" type="xs:int" use="required" />

                                <xs:unique name="UniqueC">
                                    <xs:selector xpath="tbd:C" />
                                    <xs:field xpath="@id" />
                                </xs:unique>

                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>

                    <xs:unique name="UniqueB">
                        <xs:selector xpath="tbd:B" />
                        <xs:field xpath="@id" />
                    </xs:unique>

                </xs:element>
            </xs:sequence>
        </xs:compleyType>
    </xs:element>
</xs:schema>

What I'm looking for is a validation like type="xs:ID" but not for the whole document but only inside of A so that the following example would be invalid (right now this would be valid):

<?xml version="1.0" encoding="utf-8"?>
<root xmlns="tbd">
    <A>
        <B id="01">
            <C id="01" /> <!-- should be invalid -->
            <C id="02" />
            <C id="04" />
        </B>
        <B id="04"> <!-- should be invalid -->
            <C id="02" /> <!-- should be invalid -->
            <C id="05" />
        </B>
    </A>
    <A>
        <B id="01">
            <C id="012" />
            <C id="02" />
            <C id="04" />
        </B>
        <B id="042">
            <C id="05" />
        </B>
    </A>
</root>

Upvotes: 2

Views: 505

Answers (1)

sergioFC
sergioFC

Reputation: 6016

xs:selector is used to select a list of nodes accross which the field value should be unique. So, if you want id to be unique across every B and every C then you need to select all that nodes in the selector. Example (note that in XPath the | character means union of nodes):

<xs:selector xpath="tbd:B | tbd:B/tbd:C" />

Upvotes: 1

Related Questions