Question

I have the following xml:

<animals>
   <animal name="Pongo" animalType="Dog" />
   <animal name="Marie" animalType="Cat" />
   <animal name="Skippy" animalType="Kangaroo" />
</animals>

I know it is possible to restrict the type of animals using an enum like this:

<xs:simpleType name="animalType">
    <xs:restriction base="xs:string">
        <xs:enumeration value="Cat" />
        <xs:enumeration value="Dog" />
        <xs:enumeration value="Kangaroo" />
    </xs:restriction>
</xs:simpleType>

What I whould like is to know automatically, based on the animalType value, how many shoes does the animal need, after the xml parsing.
And, when a new animal type is being added, to add also the number of walking legs for that animal.
For instance, it would be great to be possible to define something like

<xs:simpleType name="animalType">
    <xs:restriction base="xs:string">
        <xs:enumeration value="Cat" nbOfShoes="4" />
        <xs:enumeration value="Dog" nbOfShoes="4" />
        <xs:enumeration value="Kangaroo" nbOfShoes="2" />
    </xs:restriction>
</xs:simpleType>

Is it possible to achieve this using xsd, or I have to implement the numberOfShoes logic after the xml is being parsed?
Thank you.

Was it helpful?

Solution

It depends. In XSD you can define xml from structure point of view. The relation between structure and content is more difficult to express in XSD 1.0.

You could use substitution of types using xsi:type attribute. The XSD could look like

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

    <!-- Let be Animals root element -->
    <xs:element name="Animals" type="animals" />

    <!-- type for Animals elemes -->
    <xs:complexType name="animals">
        <xs:sequence>
            <xs:element name="Animal" maxOccurs="unbounded"  type="animal"/>
        </xs:sequence>
    </xs:complexType>

    <!-- Define an abstract type for animal (abstract = there shouldn't occure element of this type only of its childs). It has no attributes. -->
    <xs:complexType name="animal" abstract="true">
        <xs:simpleContent>
            <xs:extension base="xs:string"/>
        </xs:simpleContent>
    </xs:complexType>

    <!-- Define a type for cat... -->
    <xs:complexType name="catType">
        <xs:simpleContent>
            <!-- ... it extends abstract animal type ... -->
            <xs:extension base="animal">
                <!-- ... and add some attributes with fixed values -->
                <xs:attribute name="name" fixed="cat" />
                <xs:attribute name="nbOfLegs" fixed="4" />
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>

    <!-- similar definition like catType -->
    <xs:complexType name="kangarooType">
        <xs:simpleContent>
            <xs:extension base="animal">
                <xs:attribute name="name" fixed="kangaroo" />
                <xs:attribute name="nbOfLegs" fixed="2" />
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>

</xs:schema>

Following XML should validate

<?xml version="1.0" encoding="UTF-8"?>
<Animals xsi:noNamespaceSchemaLocation="animals.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <!-- xsi:type is saying what type is actually used -->
    <Animal xsi:type="catType" name="cat" nbOfLegs="4" />
    <Animal xsi:type="kangarooType" name="kangaroo" nbOfLegs="2" />
</Animals>

Following not

<?xml version="1.0" encoding="UTF-8"?>
<Animals xsi:noNamespaceSchemaLocation="animals.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Animal xsi:type="catType" name="cat" nbOfLegs="2" />
</Animals>

(with error like Value '2' of attribute 'nbOfLegs' is not equal to the fixed default value '4').

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top