简体   繁体   中英

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? Ie 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.

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.

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM