2

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.

tearvisus
  • 2,013
  • 2
  • 15
  • 32

2 Answers2

2

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.

Community
  • 1
  • 1
kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • #1 would be the best, I agree. However, in this special case I'm limited by some legacy code and old protocols. #2 will solve my problems. – tearvisus Oct 21 '15 at 15:34
1

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>
potame
  • 7,597
  • 4
  • 26
  • 33