tearvisus
tearvisus

Reputation: 2033

Is it possible to restrict the root element to a type derived from a specified parent type?

Let's start with a simple schema:

<xs:complexType name="AnimalType" abstract="true">
    <xs:sequence>
        <xs:element name="legs" xml:base="xs:nonNegativeInteger"/>
    </xs:sequence>
</xs:complexType>

<xs:complexType name="DogType">
    <xs:complexContent>
        <xs:extension base="AnimalType">
            <xs:sequence>
                <xs:element name="furColor" xml:base="xs:string"/>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

<xs:complexType name="BirdType">
    <xs:complexContent>
        <xs:extension base="AnimalType">
            <xs:sequence>
                <xs:element name="canFly" xml:base="xs:boolean"/>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

Is it possible to define a root xs:element named pet that can be of any animal type? I.e. to make both of those documents valid:

<!-- a dog -->
<pet>
    <legs>4</legs>
    <furColor>black</furColor>
</pet>


<!-- a bird -->
<pet>
    <legs>2</legs>
    <canFly>true</canFly>
</pet>

Adding <xs:element name="pet" type="AnimalType"/> does not work, because AnimalType is abstract (and even if it wasn't I still wouldn't be able to add child elements from a derived type).

I need the pet to be an instance of the AnimalType, so setting the pet's type to xs:anyType is not an option.

Upvotes: 2

Views: 91

Answers (2)

potame
potame

Reputation: 7905

One possibility is to explicitely assign the type of the element thanks to xsi:type.

In the case of the dog, you can use (assuming your schema has been save in animals.xsd):

<?xml version="1.0" encoding="UTF-8"?>
<pet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="animals.xsd" xsi:type="DogType">
    <legs>4</legs>
    <furColor>red</furColor>
</pet>

And for the bird:

<?xml version="1.0" encoding="UTF-8"?>
<pet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="animals.xsd" xsi:type="BirdType">
    <legs>2</legs>
    <canFly>true</canFly>
</pet>

Upvotes: 1

kjhughes
kjhughes

Reputation: 111726

No, and the fact that a comment is needed to differentiate the two pet cases should be taken as a signal that the XML design goal should be questioned here rather than the capabilities of XSD.

Here are a couple alternative XML designs:

  1. A document can have different root node possibilities, so simply permit both dog and bird root elements, with their respective types both derived from a common AnimalType.
  2. XSD 1.1 supports Conditional Type Assignment (CTA), so add an attribute to AnimalType that could be tested to differentiate the DogType and BirdType alternative possibilities of a pet root element. You can find an example of CTA here.

I would favor #1.

Upvotes: 2

Related Questions