Ian
Ian

Reputation: 5735

XSD: One and only one element of a certain type should be declared

Say that I have a PetCage element that should contains one and only one AnimalElement type like so:

<PetCage>
    <Cat Name="Kitty">
</PetCage>

<PetCage>
    <Dog Name="Buddy">
</PetCage>

Both Cat and Dog are of AnimanlElement type. How can I express said rule in XSD?

Upvotes: 1

Views: 8488

Answers (2)

G_H
G_H

Reputation: 12019

What you require is a choice element in your schema. It'll allow you to express that only one from a set of elements may appear.

EDIT: you'll need to specify a name for the element, either directly via name or in reference to an element defined elsewhere via ref.

Your only alternative as far as I know is to have something like this:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">

    <xs:element name="PetCage">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="animal" type="Animal" minOccurs="1" maxOccurs="1"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="Animal" abstract="true">
        <xs:attribute name="Name" type="xs:string" />
    </xs:complexType>

    <xs:complexType name="Cat">
        <xs:complexContent>
            <xs:extension base="Animal"></xs:extension>
        </xs:complexContent>
    </xs:complexType>

</xs:schema>

This would validate XML files of a form like this:

<?xml version="1.0" encoding="UTF-8"?>
<PetCage>
    <animal xsi:type="Cat" Name="String"/>
</PetCage>

Unfortunately this leaves you tied to that animal element name. I doubt that XML Schema allows you to specify a specific type and lets you use a wildcard for the name. XML Schema validates based on element names and, if the element is defined with an abstract type, the xsi:type attribute. There is an xs:any declaration, but that can't be tied to any specific type. The following will validate as best as possible, but still allows any element defined under the schema root to be used:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">

    <xs:element name="PetCage">
        <xs:complexType>
            <xs:sequence>
                <xs:any processContents="strict" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="Animal" abstract="true">
        <xs:attribute name="Name" type="xs:string" />
    </xs:complexType>

    <xs:element name="cat" />
    <xs:complexType name="Cat">
        <xs:complexContent>
            <xs:extension base="Animal"></xs:extension>
        </xs:complexContent>
    </xs:complexType>

</xs:schema>

It would validate this correctly:

<?xml version="1.0" encoding="UTF-8"?>
<PetCage>
    <cat Name="snookums"/>
</PetCage>

... but it wouldn't stop you from putting a PetCage in a PetCage.

I'm hoping someone with good knowledge of the XML Schema spec can confirm that this is correct or, preferably, offer the desired solution.

Upvotes: 3

tom redfern
tom redfern

Reputation: 31780

<xs:complexType name="PetCage">
    <xs:choice>
         <xs:element name="Cat" type="AnimanlElement" />
         <xs:element name="Dog" type="AnimanlElement" />
    </xs:choice>
</xs:complexType>
<!-- AnimanlElement definition -->
<xs:complexType name="AnimanlElement">
    <xs:attribute name="Name" type="xs:string" />
</xs:complexType>

For more: http://www.w3schools.com/Schema/el_choice.asp

Upvotes: 2

Related Questions