zapletnev
zapletnev

Reputation: 503

Specify root element with general child element in XSD

I have base class for all child elements in my XSD

<xs:complexType name="BaseItem">
    <xs:attribute name="id" type="string" use="required"/>
</xs:complexType>

And extenders of this element

<xs:complexType name="Package">
    <xs:complexContent>
        <xs:extension base="BaseItem">
            <xs:sequence>
                <xs:element name="SubElement" type="SubElementType"/>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

<xs:complexType name="Class">
    <xs:complexContent>
        <xs:extension base="BaseItem">
            <xs:sequence>
                <xs:element name="SubElement2" type="SubElementType2"/>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>
.......
etc....

And xml examples for this XSD:

XML1: <Root><Package id="xxx"><SubElement/></Package></Root>

XML2: <Root><Class id="xxx"><SubElement2/></Class></Root>

XML3: <Root><Method id="xxx"><SubElement3/></Method></Root>

XML4: <Root><Method id="xxx"><SubElement3/></Method></Root>

How I can specify root element in this XSD without defining all possible children?

<xs:element name="Root"> <xs:complexType> <xs:sequence> //????? </xs:sequence> </xs:complexType> </xs:element>

Is any way to specify children through base type? Smth:

<xs:element name="Root"> <xs:complexType> <xs:sequence> <element type="BaseItem"/> </xs:sequence> </xs:complexType> </xs:element>

Or without specifying name of element this is impossible?

Upvotes: 1

Views: 1885

Answers (1)

Jirka Š.
Jirka Š.

Reputation: 3428

You could use substitution group (http://www.w3schools.com/schema/schema_complex_subst.asp) in this way

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:complexType name="base_item_type">
        <xs:attribute name="id" type="xs:string" use="required"/>
    </xs:complexType>

    <xs:complexType name="package_type">
        <xs:complexContent>
            <xs:extension base="base_item_type">
                <xs:sequence>
                    <xs:element name="SubElement" type="xs:string"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>

    <xs:complexType name="class_type">
        <xs:complexContent>
            <xs:extension base="base_item_type">
                <xs:sequence>
                    <xs:element name="SubElement2" type="xs:string"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>

    <!-- abstract attribute to prevent occurence of BaseElement-->
   <xs:element name="BaseElement" type="base_item_type" abstract="true"/>

    <!-- Package and Class element might be used instead of BaseElement-->
    <!-- But they also can be put as root element -->
    <xs:element name="Package" type="package_type" substitutionGroup="BaseElement" /> 
    <xs:element name="Class" type="class_type" substitutionGroup="BaseElement"/>

    <!-- Root element -->
    <xs:element name="RootElement">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="BaseElement" maxOccurs="unbounded" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

</xs:schema>

But I'm not sure if it is better than choice in the root element - just because in this way also "package" and "class" can be put as a root element directly. Personally I would prefer one root element with (although bigger) choice.

Upvotes: 2

Related Questions