Paul Richards
Paul Richards

Reputation: 1207

XSD: restrict content to be equal to grandparent if it is present

Can you use an XSD to restrict the content of an XML element to be equal to its grandparent? So that this passes validation:

<pupil>
<pupilid>342424</pupilid>
<name>John Smith</name>
<assessment>
<assessmentid>1</assessmentid>
<pupilid>342424</pupilid>
</assessment>
</pupil>

And this fails validation:

<pupil>
<pupilid>342424</pupilid>
<name>John Smith</name>
<assessment>
<assessmentid>1</assessmentid>
<pupilid>666</pupilid>
</assessment>
</pupil>

Upvotes: 1

Views: 102

Answers (1)

Petru Gardea
Petru Gardea

Reputation: 21658

You could do it if you consider the above as referential integrity. One could easily say that there is redundant information, but I've also seen it due to model reuse.

This is what your XML looks like:

enter image description here

This is what the XSD would then look like:

enter image description here

And the source:

<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="pupil">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="pupilid" type="xsd:unsignedInt"/>
                <xsd:element name="name" type="xsd:string"/>
                <xsd:element name="assessment">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="assessmentid" type="xsd:unsignedByte"/>
                            <xsd:element name="pupilid" type="xsd:unsignedInt"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
        <xsd:key name="PK">
            <xsd:selector xpath="pupilid"/>
            <xsd:field xpath="."/>
        </xsd:key>
        <xsd:keyref name="FK" refer="PK">
            <xsd:selector xpath="assessment/pupilid"/>
            <xsd:field xpath="."/>
        </xsd:keyref>
    </xsd:element>
</xsd:schema>

Your first XML would pass validation, while the second may yield:

Error occurred while loading [], line 8 position 3 The key sequence '666' in Keyref fails to refer to some key. xsd-restrict-content-to-be-equal-to-grandparent-if-it-is-present.xml is XSD 1.0 invalid.

As long as these kind of constraints can be modeled similar to what referential integrity means for database people, then key/unique and keyref can help.

For more general co-constraints, you would have to either move to XSD 1.1 or use Schematron in addition to XSD 1.0.

Upvotes: 2

Related Questions