PlikPlok
PlikPlok

Reputation: 110

XSD restrict tag content depending upon attribute value

I would like define an XSD that allows an element to have specific children regarding one of its attribute value. This attribute values are defined using multiple xsd:enumeration.

Here is how my XML can be :

<root>
    <Conversion type="Phys" />
    <Conversion type="Fact">
        <Factor>13</Factor>
        <Offset>37</Offset>
    </Conversion>
    <Conversion type="List">
        <Item>
            <Key>0</Key>
            <Value>KEY_0</Value>
        </Item>
        <Item>
            <Key>1</Key>
            <Value>KEY_1</Value>
        </Item>
    </Conversion>
</root>

So far, I have managed to restrict the Conversion tag to have only these 3 attributes and only these 3 sequences as children (Factor/Offset ; Item list ; nothing).

Here is a bit of my XSD :

<xs:element name="Conversion">
    <xs:complexType>
        <xs:choice>
            <xs:sequence>
                <xs:element name="Item" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="Key" type="xs:decimal" />
                            <xs:element name="Value" type="xs:string" />
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
            <xs:sequence>
                <xs:element name="Factor" type="xs:double" />
                <xs:element name="Offset" type="xs:double" />
            </xs:sequence>
            <xs:sequence />
        </xs:choice>
        <xs:attribute name="Type">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:enumeration value="Fact" />
                    <xs:enumeration value="List" />
                    <xs:enumeration value="Phys" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
    </xs:complexType>
</xs:element>

What I would like to do is to restrict the children according to the value of my attribute to avoid forbid mixing attributes and contents.

Upvotes: 1

Views: 477

Answers (1)

kjhughes
kjhughes

Reputation: 111491

You'll need XSD 1.1 to do exactly what you request, make a content model dependent upon the value of an attribute. You can use Conditional Type Assignment or even assertions.

However, if you can adjust your XML design, you can use basic XSD 1.0 (and XSD 1.1 as well):

<root>
    <Phys/>
    <Fact>
        <Factor>13</Factor>
        <Offset>37</Offset>
    </Fact>
    <List>
        <Item>
            <Key>0</Key>
            <Value>KEY_0</Value>
        </Item>
        <Item>
            <Key>1</Key>
            <Value>KEY_1</Value>
        </Item>
    </List>
</root>

Type information is generally better conveyed via a more specific element name than via augmentation of a generic element name with a type attribute.

Upvotes: 3

Related Questions