agf1997
agf1997

Reputation: 2888

XML Schema element restrictions based on usage

I've defined a element named transform

<xs:element name="transformName" type="xs:string"/>

I'd like to use that element in various other elements. For example

<xs:element name="input">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="transformName"/>
            <xs:element name="description" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:element name="output">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="transformName"/>
            <xs:element name="description" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

I know I can restrict what can be put in transform name using something like

<xs:element name="transformName">
    <xs:simpleType>
        <xs:restriction base="xs:string">
            <xs:pattern value="transform\.\S+\.\S+\.\d{1}\.v\d+"/>
        </xs:restriction>
    </xs:simpleType>
</xs:element>

But is there any way to vary the restriction for each parent element?

For example, when used in input it might be:

<xs:restriction base="xs:string">
    <xs:pattern value="inputTransform\.\S+\.\d{1}"/>
</xs:restriction>

But when used in output it might be:

<xs:restriction base="xs:string">
    <xs:pattern value="outputTransform\.\S+\.\d{1}"/>
</xs:restriction>

Upvotes: 0

Views: 200

Answers (1)

zx485
zx485

Reputation: 29022

Because you say that you are restricted to XSD-1.0, I avoid using xs:alternative. By

"Define a type for each possibility/parent element."

I do mean to create a type for each xs:pattern.
So, for a sample XML like this:

<root>
    <input>
        <transformName>inputTransform.A.1</transformName>
        <description />
    </input>
    <output>
        <transformName>outputTransform.C.2</transformName>
        <description />
    </output>
</root>

...the XSD-1.0 code that validates it could look like this:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:element name="root">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="input">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="transformName" type="tnInput" />
                            <xs:element name="description" type="xs:string" />
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="output">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="transformName" type="tnOutput" />
                            <xs:element name="description" type="xs:string" />
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:simpleType name="tnInput">
        <xs:restriction base="xs:string">
            <xs:pattern value="inputTransform\.\S+\.\d{1}"/>
        </xs:restriction>
    </xs:simpleType>

    <xs:simpleType name="tnOutput">
        <xs:restriction base="xs:string">
            <xs:pattern value="outputTransform\.\S+\.\d{1}"/>
        </xs:restriction>
    </xs:simpleType>

</xs:schema>

See that it defines a different simpleType with a different xs:pattern for each parent element (input/output).


To avoid this, you'd have to use the XSD-1.1 xs:alternative approach which could look like this:

<xs:element name="transformName" type="xs:string">
    <xs:alternative test="ancestor::input"  type="inputType"/>
    <xs:alternative test="ancestor::output" type="outputType"/>
</xs:element>

I couldn't make this work, but it's the way to go if you want to keep one element as a reference.

Upvotes: 1

Related Questions