Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding and Changing An Xml Element In The Base Type

I have an xml schema that defines the basic fields for a car:

<xs:simpleType name="FuelType">
    <xs:restriction base="xs:string">
        <xs:enumeration value="Regular Unleaded"/>
        <xs:enumeration value="High Octane"/>
        <xs:enumeration value="Leaded"/>
    </xs:restriction>
</xs:simpleType>
<xs:complexType name="CarType">
    <xs:sequence>
        <xs:element name="Make" type="xs:string"/>
        <xs:element name="Model" type="xs:string"/>
        <xs:element name="Cylinders" type="xs:int"/>
        <xs:element name="Fuel" type="FuelType"/>
    </xs:sequence>
</xs:complexType>

Now let's say I want to define a Honda car type that extends from CarType but has it's own definition for Fuel:

<xs:simpleType name="HondaFuelType">
    <xs:restriction base="xs:string">
        <xs:enumeration value="85"/>
        <xs:enumeration value="87"/>
        <xs:enumeration value="89"/>
        <xs:enumeration value="91"/>
        <xs:enumeration value="93"/>
        <xs:enumeration value="95"/>
    </xs:restriction>
</xs:simpleType>
<xs:complexType name="HondaCarType">
    <xs:complexContent>
        <xs:extension base="car:CarType">
            <xs:sequence>
                <xs:element name="Fuel" type="HondaFuelType"/>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

Extending CarType gets me everything I want however the schema now allows for two elements named Fuel (in different namespaces). Here is a sample Xml instance:

<HondaCar xmlns="HondaNS" xmlns:car="CarNS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="HondaNS D:\Development\Temp\honda.xsd">
    <car:Make/>
    <car:Model/>
    <car:Cylinders>4</car:Cylinders>
    <car:Fuel>High Octane</car:Fuel>
    <Fuel>87</Fuel>
</HondaCar>

Although this is perfectly valid Xml it doesn't make logical sense (to me at least). My intention was to extend the base type then override *Fuel* to only allow the values defined in HondaFuelType.

Is there a way I can override or mask the base Fuel element in my extended type?

like image 843
Jan Tacci Avatar asked Jan 18 '13 03:01

Jan Tacci


People also ask

What is the difference between element and attribute in XSD?

An attribute provides extra information within an element. Attributes are defined within an XSD as follows, having name and type properties. An Attribute can appear 0 or 1 times within a given element in the XML document. Attributes are either optional or mandatory (by default the are optional).

Are XML attributes optional?

Defining XML AttributesAttributes are either optional or mandatory (by default they are optional). The "use" property in the XSD definition is used to specify if the attribute is optional or mandatory.

Can Xsd have multiple root elements?

While a properly formed XML file can only have a single root element, an XSD or DTD file can contain multiple roots.


1 Answers

You can do things very similar to what you describe, but it is not possible in XSD to do precisely what you describe. The 'base' declaration of complex type CarType makes a number of commitments to the data consumer, which must be obeyed by all types derived from it, whether by restriction or extension. Among these are:

  • Instances of CarType will have children named Make, Model, Cylinders, and Fuel, with the types indicated.
  • The values of the Make and Model elements will be strings.
  • The value of the Cylinders element will be an xs:int.
  • The value of the Fuel element will be drawn from the set of strings {"Regular Unleaded", "Leaded", "High Octane"}.

It's the last of these commitments you are running intro trouble with.

When you extend a type, you add new children at the end of its content model; for XSD 1.0 it will always be true that for any element valid against an extension, it's possible to drop zero or more children from the end and produce an element which would be valid against the base type. That's why your extension ends up with two Fuel elements.

If you only want one Fuel element, then what you want to do is restrict, not extend, CarType. But the restriction you have in mind isn't a legal restriction of the base type's Fuel element. So restriction won't work for you here, either.

One possibility, of course, is to generalize CarType so that its Fuel element to accept xs:string, and then restrict it twice, once to produce something like the existing CarType, and once to produce the Honda variation you have in mind.

I hope this helps.

like image 95
C. M. Sperberg-McQueen Avatar answered Sep 21 '22 03:09

C. M. Sperberg-McQueen