Consider the following scenario:
I want to save elements and their attributes in a database, these elements extend from a common but abstract supertype called "PersistentElement". Now some of these elements all have a particular attribute, e.g. they all have a name, and all of these elements again share a common superelement named "NamedElement", which again is abstract. That leads to a schema/XSD looking like this:
<xs:element name="Database">
<xs:complexType>
<xs:sequence>
<xs:element name="elements" type="PersistentElement" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="PersistentElement" abstract="true">
<xs:attribute name="id" type="xs:ID"/>
</xs:complexType>
<xs:complexType name="NamedElement" abstract="true">
<xs:complexContent>
<xs:extension base="PersistentElement">
<xs:attribute name="name" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="ElementWithName">
<xs:complexContent>
<xs:extension base="NamedElement">
<xs:element name="somethingElse" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
Now my question: is this even possible in XML? The most obvious fix for that would be to make one of the abstract elements a xs:choice-type of element, but just out of curiousity, and because I am still learning, I would like to know if a double extended abstract element is possible. The problem I face is, that I can't (or more exact do not know how to) instantiate a such a element in the corresponding XML file. What I want is:
<Database>
<elements xsi:type="ElementWithName" id = "E1" name="testElement1" >
<somethingElse>bla</somethingElse>
</elements>
<elements xsi:type="ElementWithName" id = "E2" name="testElement2" >
<somethingElse>blub</somethingElse>
</elements>
</Database>
But this gives me an error when I try to validate this,
Cvc-elt.4.2: Cannot Resolve 'ElementWithName' To A Type Definition For Element 'elements'.. Line '13', Column '66'.
Cvc-type.2: The Type Definition Cannot Be Abstract For Element Elements.. Line '13', Column '66'.
Cvc-complex-type.3.2.2: Attribute 'name' Is Not Allowed To Appear In Element 'elements'.. Line '13', Column '66'.
Cvc-complex-type.2.1: Element 'elements' Must Have No Character Or Element Information Item [children], Because The Type's Content Type Is Empty.. Line '16', Column '16'.
Yes, you can extend an already extended type.
The error message that Xerces gives for your XSD is:
s4s-elt-invalid-content.1: The content of 'ElementWithName' is invalid. Element 'element' is invalid, misplaced, or occurs too often.
Wrapping xs:element/@name="somethingElse"
in a xs:sequence
resolves this error.
Here is the complete, corrected XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="Database">
<xs:complexType>
<xs:sequence>
<xs:element name="elements" type="PersistentElement" minOccurs="0"
maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="PersistentElement" abstract="true">
<xs:attribute name="id" type="xs:ID"/>
</xs:complexType>
<xs:complexType name="NamedElement" abstract="true">
<xs:complexContent>
<xs:extension base="PersistentElement">
<xs:attribute name="name" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="ElementWithName">
<xs:complexContent>
<xs:extension base="NamedElement">
<xs:sequence>
<xs:element name="somethingElse" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
Here is a valid XML document per the above XSD:
<?xml version="1.0" encoding="UTF-8"?>
<Database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="Database.xsd">
<elements xsi:type="ElementWithName" id = "E1" name="testElement1" >
<somethingElse>bla</somethingElse>
</elements>
<elements xsi:type="ElementWithName" id = "E2" name="testElement2" >
<somethingElse>blub</somethingElse>
</elements>
</Database>