ilomambo
ilomambo

Reputation: 8350

How to set restriction on XSD for id attributes

If I wanted to define an XSD file for:

<state id="1" name="S1">
<state id="2" name="S2">
<state id="3" name="S3">

<transition fromState="1" toState="2">

How can I restrict, in the XSD file, the attributes fromState and toState to get only values that were declared on the state elements id?

The XSD definition does not seem to have such feature, but take Android XML layouts, somehow the Eclipse Android XML editor knows which ids to put in the content assisted list.

Upvotes: 1

Views: 1745

Answers (1)

Petru Gardea
Petru Gardea

Reputation: 21638

The recommended way is to use unique/key/keyref constructs. Considering this modified XML (to add a document element):

<Document>
    <state id="1" name="S1"/>
    <state id="2" name="S2"/>
    <state id="3" name="S3"/>

    <transition fromState="1" toState="2"/>
</Document>

enter image description here

This XSD does exactly what you want:

<?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="Document">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element maxOccurs="unbounded" name="state">
                    <xsd:complexType>
                        <xsd:attribute name="id" type="xsd:unsignedByte" use="required"/>
                        <xsd:attribute name="name" type="xsd:string" use="required"/>
                    </xsd:complexType>
                </xsd:element>
                <xsd:element name="transition">
                    <xsd:complexType>
                        <xsd:attribute name="fromState" type="xsd:unsignedByte" use="required"/>
                        <xsd:attribute name="toState" type="xsd:unsignedByte" use="required"/>
                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
        <xsd:key name="PKStates">
            <xsd:selector xpath="state"/>
            <xsd:field xpath="@id"/>
        </xsd:key>
        <xsd:keyref name="FKTransitionToStatesFrom"  refer="PKStates">
            <xsd:selector xpath="transition"/>
            <xsd:field xpath="@fromState"/>
        </xsd:keyref>
        <xsd:keyref name="FKTransitionToStatesTo" refer="PKStates">
            <xsd:selector xpath="transition"/>
            <xsd:field xpath="@toState"/>
        </xsd:keyref>
    </xsd:element>
</xsd:schema>

enter image description here

If you take a look at the diagrams, you can more easily visualize how selectors work. If you decide to use this and if your XSD has a target namespace and if you qualify your elements and/or attributes, make sure that you declare a prefix for the targetNamespace and use that prefix in your XPath.

In general, not many tools though know how use this information (key/keyref) to build content assisted lists to facilitate XML editing based on the associated XSD. Usually editors with a specialized nature would do that, based on hardwired implementations rather than inference from XSD only.

Upvotes: 2

Related Questions