Shorten the XSD

193 views Asked by At

I have a XML and a corresponding XSD as follows:

myXSD.xsd :

<?xml version="1.0"  encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.com/myXSD"
    xmlns="http://www.example.com/myXSD"
    elementFormDefault="qualified">

    <xs:element name="RootElem">
        <xs:complexType>
            <xs:sequence>

                <xs:element name="Insider1">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element ref="Internal" maxOccurs="unbounded" />
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>

                <xs:element name="Insider2">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element ref="Internal" maxOccurs="unbounded" />
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>

                <xs:element name="Insider3">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element ref="Internal" maxOccurs="unbounded" />
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>

            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="Internal-low">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="myString" type="xs:string" maxOccurs="unbounded"></xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="Internal">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Step" type="xs:string"></xs:element>
                <xs:element ref="Internal-low" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

</xs:schema>

myXML.xml :

<?xml version="1.0" encoding="UTF-8"?>

<RootElem xmlns="http://www.example.com/myXSD"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.example.com/myXSD myXSD.xsd">
    <Insider1>
        <Internal>
            <Step>My step 1</Step>
            <Internal-low>
                <myString>My string 1 for step 1</myString>
            </Internal-low>
        </Internal>
        <Internal>
            <Step>My step 2</Step>
            <Internal-low>
                <myString>My string 1 for step 2</myString>
            </Internal-low>
        </Internal>
        <Internal>
            <Step>My step 3</Step>
            <Internal-low>
                <myString>My string 1 for step 3</myString>
                <myString>My string 2 for step 3</myString>
            </Internal-low>
        </Internal>
    </Insider1>
    <Insider2>
        <Internal>
            <Step>My step 1</Step>
            <Internal-low>
                <myString>My string 1 for step 1</myString>
            </Internal-low>
        </Internal>
        <Internal>
            <Step>My step 2</Step>
            <Internal-low>
                <myString>My string 1 for step 2</myString>
            </Internal-low>
        </Internal>
        <Internal>
            <Step>My step 3</Step>
            <Internal-low>
                <myString>My string 1 for step 3</myString>
                <myString>My string 2 for step 3</myString>
            </Internal-low>
        </Internal>
    </Insider2>
    <Insider3>
        <Internal>
            <Step>My step 1</Step>
            <Internal-low>
                <myString>My string 1 for step 1</myString>
            </Internal-low>
        </Internal>
        <Internal>
            <Step>My step 2</Step>
            <Internal-low>
                <myString>My string 1 for step 2</myString>
            </Internal-low>
        </Internal>
        <Internal>
            <Step>My step 3</Step>
            <Internal-low>
                <myString>My string 1 for step 3</myString>
                <myString>My string 2 for step 3</myString>
            </Internal-low>
        </Internal>
    </Insider3>

</RootElem>

Everything works fine here. The problem is with the InsiderX elements. There are about 10 InsiderX elements in my actual XSD which may be increasing over time. So I need to compress the XSD code so that adding or removing any InsiderX element is simpler as doing so now requires adding/removing 7 lines of redundant code. And how can I make sure that one and only one of each of the InsiderX element occurs in my XML.

Also I would like to know what are other options in a XSD to replace <xs:sequence>. I don't want alternate to this, but want to know what are other possible options like <xs:choice>.

2

There are 2 answers

0
Kohányi Róbert On BEST ANSWER

I need to compress the XSD code so that adding or removing any InsiderX element is simpler as doing so now requires adding/removing 7 lines of redundant code

You can shorten your XSD by creating a reusable type like this.

<xs:complexType name="InsiderXType">
    <xs:sequence>
        <xs:element ref="Internal" maxOccurs="unbounded" />
    </xs:sequence>
</xs:complexType>

<xs:element name="RootElem">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="Insider1" type="InsiderXType"/>
            <xs:element name="Insider2" type="InsiderXType"/>
            <xs:element name="Insider3" type="InsiderXType"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

how can I make sure that one and only one of each of the InsiderX element occurs in my XML

You've already covered this scenario with your original schema. Modify your XML document by duplicating the Insider1 node for example like this

<Insider1>
    ...
</Insider1>
<Insider1>
    ...
</Insider1>
<Insider2>
   ...

and try to validate this against your schema. You'll get an error something like this: cvc-complex-type.2.4.a: Invalid content was found starting with element 'Insider1'. One of '{"http://www.example.com/myXSD":Insider2}' is expected.

I would like to know what are other options in a XSD to replace <xs:sequence>

Well I'm not sure how to answer this, because this question is really too broad, however take a look at the XML Schema specification for complex type definitions. It says that instead of a sequence you can use group, all or choice. I hope this will get you on the right track.

3
flafoux On

I think it's undoable, a better way to handle this would be in your xml to have :

<Insider name="Insider1">

instead of

<Insider1>

EDIT : (restrict name attribute values)

<attribute name="name">
    <xs:simpleType>
        <xs:restriction base="xs:string">
            <xs:pattern value="Insider[0-9]*"/>
        </xs:restriction>
    </xs:simpleType>
</attribute>