Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can an XML schema require elements to be sorted by attribute?

Tags:

xml

xsd

Suppose I have an XML file that looks like this:

<Transactions>
<Transaction OrderID="5"> ... </Transaction>
<Transaction OrderID="6"> ... </Transaction>
<Transaction OrderID="11"> ... </Transaction>
<Transaction OrderID="7"> ... </Transaction>
</Transactions>

Using XML schema, is it possible to indicate that Order #11 is not in the correct sequence? Each Transaction element individually passes validation, but the OrderID should be in increasing order.

And, a related question: Can a validation rule indicate whether or not numbers can be skipped? For example, there is no transaction #8,9, or 10.

like image 477
Selecter Avatar asked Nov 10 '22 01:11

Selecter


1 Answers

If your validator supports XSD 1.1, you can use xs:assert to deny certain attribute values like this:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" 
           elementFormDefault="qualified" 
           attributeFormDefault="unqualified"
           vc:minVersion="1.1">
   <xs:element name="Transactions">
      <xs:complexType>
         <xs:sequence>
            <xs:element name="Transaction" maxOccurs="unbounded">
               <xs:complexType mixed="true">
                   <xs:attribute name="OrderID" type="xs:integer"/>
                   <xs:assert test="empty(index-of((8,9,10),@OrderID))"/>
               </xs:complexType>                                
            </xs:element>
         </xs:sequence>
      </xs:complexType>
   </xs:element>
</xs:schema>

This should answer your second question.

As for your first question, I don't think order validation is possible. You can, however, use XSLT to sort the XML document.

----- added the answer to the first question -----

Thank you, Michael Kay. Well...here is the answer to your first question.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="Transactions">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Transaction" maxOccurs="unbounded">
                    <xs:complexType mixed="true">
                        <xs:attribute name="OrderID" type="xs:integer"/>
                        <xs:assert test="empty(index-of((8,9,10),@OrderID))"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
            <xs:assert test="every $x in Transaction satisfies 
                             (empty($x/preceding-sibling::*) or 
                             ($x/@OrderID gt $x/preceding-sibling::*[1]/@OrderID))"/>
        </xs:complexType>
    </xs:element>
</xs:schema>
like image 168
Chong Lip Phang Avatar answered Dec 10 '22 19:12

Chong Lip Phang