Thursday, May 27, 2010

XSD 1.1: schema versioning, and Xerces-J support

XML Schema 1.1 provides a nice schema composition feature, called "Conditional inclusion" which allows us to include/exclude Schema components, during schema processing, based on values of certain special control attributes (minVersion & maxVersion), specified on the schema components.

Here are two simplistic examples, illustrating this feature:

Example 1

XML document [1]:
<test>3</test>

XSD 1.1 document [2]:
<?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">

      <xs:element name="test">
          <xs:simpleType>
              <xs:restriction base="xs:positiveInteger">
                 <xs:assertion test="$value mod 2 = 0" vc:minVersion="1.1" />
              </xs:restriction>
          </xs:simpleType>
      </xs:element>

</xs:schema>

In the above schema document [2], the attribute vc:minVersion on xs:assertion instruction specifies, that the assertion instruction would only be processable by XSD processors, which support 1.1 and a higher level of the XSD schema language. If this schema document [2] is run by an XSD 1.1 (and possible a higher language version in future) processor in XSD 1.0 mode, the assertion instruction would be ignored by the XSD engine. The schema versioning features allows us to have a XSD engine, ignore certain schema components (in entirety along with their descendant instructions).

Example 2

XML document [3]:
<address ver="V2">
    <street1></street1>
    <street2>XX</street2>
    <city>XX</city>
    <state>XX</state>
    <country>XX</country>
</address>


XSD 1.1 document [4]:
<?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">

     <xs:element name="address" type="Address">
         <xs:alternative test="@ver = 'V2'" type="AddressV2" vc:minVersion="1.1" />
     </xs:element>

     <xs:complexType name="Address">
        <xs:sequence>
            <xs:element name="street1" type="xs:string" />
            <xs:element name="street2" type="xs:string" />
            <xs:element name="city" type="xs:string" />
            <xs:element name="state" type="xs:string" />
            <xs:element name="country" type="xs:string" />
        </xs:sequence>
     </xs:complexType>

     <xs:complexType name="AddressV2">
         <xs:complexContent>
             <xs:extension base="Address">
                <xs:attribute name="ver" type="xs:string" />
                <xs:assert test="not(normalize-space(street1) = '')" />
             </xs:extension>
         </xs:complexContent>
     </xs:complexType>

</xs:schema>

Similarly, the above schema document ([4]) ignores the type-alternative instruction, if the XSD 1.1 processor is run in a XSD 1.0 mode. I believe, the intent of the above schema and the XML document should be clear enough (we are using an "address" element in XML document, which needs to be validated by a corresponding XML Schema type. The complex type, "AddressV2" extends the type "Address", and has an assertion specification to constrain the contents of the element "street1" -- in this particular example, the assertion on type "AddressV2" constrains the element, "street1" to have some significant white-space characters).

Xerces-J runs these examples fine.

Summarizing this post: The XSD 1.1 schema versioning features, allows us to write a XSD schema containing mix and match of XSD 1.0 and 1.1 instructions (and XSD instructions beyond XSD 1.1 level, for future!), and have the XSD 1.1 engine ignore certain XSD instructions at run-time depending, at which XSD language level, the XSD 1.1 engine was invoked.

I hope that this post is useful.