Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specify XSD such that an XML element must have the value of another XML element

Tags:

xml

xsd

I'm not sure if this is possible with XML/XSD, and haven't had much luck searching for it.

Can you specify an XSD, so that when you're writing your XML, you can have an element that must reference one of the values contained in another XML element?

For example, if you had this XML:

<car>Audi</car>
<car>Ford</car>
<car>Honda</car>

<person>
  <drives>Audi</drives>
</person>

How do you specify the XSD for drives so that it must be one of the values entered for car?

like image 796
Simon Trewhella Avatar asked Dec 15 '22 17:12

Simon Trewhella


1 Answers

XSD 1.0 would work. Ideally you should use a combination of same schema type and referential integrity.

An XSD:

<?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="sample">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element maxOccurs="unbounded" name="car" type="car"/>
                <xsd:element name="person">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="drives" type="car"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
        <xsd:key name="PKCars">
            <xsd:selector xpath="car"/>
            <xsd:field xpath="."/>
        </xsd:key>
        <xsd:keyref name="FKPersonCar" refer="PKCars">
            <xsd:selector xpath="person/drives"/>
            <xsd:field xpath="."/>
        </xsd:keyref>
    </xsd:element>
    <xsd:simpleType name="car">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="Audi"/>
            <xsd:enumeration value="Ford"/>
            <xsd:enumeration value="Honda"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>

Diagram:

enter image description here

Invalid XML:

<sample>
    <car>Audi</car>
    <car>Ford</car>
    <car>Honda</car>

    <person>
        <drives>Aud</drives>
    </person>
</sample>

Error:

Error occurred while loading [], line 7 position 16
The 'drives' element is invalid - The value 'Aud' is invalid according to its datatype 'car' - The Enumeration constraint failed.
specify-xsd-such-that-an-xml-element-must-have-the-value-of-another-xml-element.xml is invalid.

This error tells you that using an enumerated value makes key/keyref superfluous - you'll not get to trigger it.

However, if you cannot have a list of enumerated values in your XSD, you should at least enforce a mininum length for the type, to avoid empty values creating havoc. Of course, while it is recommended to share the type, you don't have to.

Modified XSD:

<?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="sample">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element maxOccurs="unbounded" name="car" type="car"/>
                <xsd:element name="person">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="drives" type="car"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
        <xsd:key name="PKCars">
            <xsd:selector xpath="car"/>
            <xsd:field xpath="."/>
        </xsd:key>
        <xsd:keyref name="FKPersonCar" refer="PKCars">
            <xsd:selector xpath="person/drives"/>
            <xsd:field xpath="."/>
        </xsd:keyref>
    </xsd:element>
    <xsd:simpleType name="car">
        <xsd:restriction base="xsd:normalizedString">
            <xsd:minLength value="1"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>

Error message:

Error occurred while loading [], line 9 position 4
The key sequence 'Aud' in Keyref fails to refer to some key.
specify-xsd-such-that-an-xml-element-must-have-the-value-of-another-xml-element.xml is invalid.
like image 90
Petru Gardea Avatar answered May 26 '23 12:05

Petru Gardea