简体   繁体   中英

Restrict order of XML elements based on attribute

I have the following XML:

<?xml version="1.0"?>

<coll xmlns="http://www.example.org/coll" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.example.org/coll coll.xsd">

    <collection>
        <item action="remove">1</item>
        <item action="add">2</item>
        <item action="add">3</item>
    </collection>

    <collection>
        <item action="add">2</item>
        <item action="remove">1</item>
        <item action="add">3</item>
    </collection>

</coll>   

And an XSD:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/coll"
    xmlns:tns="http://www.example.org/coll" elementFormDefault="qualified">

    <element name="coll" type="tns:coll">
    </element>

    <complexType name="coll">
        <sequence>
            <element name="collection" type="tns:collection" minOccurs="0" maxOccurs="unbounded"></element>
        </sequence>
    </complexType>

    <complexType name="collection">
        <sequence>
            <element name="item" type="tns:item" minOccurs="0" maxOccurs="unbounded"></element>
        </sequence>
    </complexType>

    <complexType name="item">
        <simpleContent>
            <extension base="string">
                <attribute name="action">
                    <simpleType>
                        <restriction base="string">
                            <enumeration value="add"></enumeration>
                            <enumeration value="remove"></enumeration>
                        </restriction>
                    </simpleType>
                </attribute>
            </extension>
        </simpleContent>
    </complexType>

</schema>

I would like to restrict the order of the item elements such that the removes always comes before the adds. Ie the first collection is valid but the second one is invalid.

I've tried with two item elements, one with an add_item type and one with remove_item. But this fails to validate the XSD with the error that I can not have two elements of the same name with different types.

Any ideas? Or is it even possible?

The only way this is possible (with XSD) would be by refactoring your schema to use the action as the element name instead of an attribute:

<collection>
    <remove>1</remove>
    <add>2</add>
    <add>3</add>
</collection>

That way, you can use a sequence in your schema to determine the order.

On a more general note: Your schema design looks a bit mixed up. Your element names seem to describe a state (collection, item), yet your attributes on item seem to carry the actual information about an action your code is (presumably) to take. If you have a choice about the design, you might want to think about a slight redesign.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM