Thursday, December 10, 2009

Xerces-J: XSD 1.1 assertions implementation updates

There have been some improvements lately, to the XSD 1.1 assertions support in Xerces-J.

Here are the summary of recent assertion implementation changes, in Xerces-J:

1) XPath 2 expressions, in assertion facets should not access the XPath 2 context, because XPath context is "undefined" during assert facet evaluation

This implies that, the right way to invoke assertion facets, is as follows:
  <xs:simpleType>
    <xs:restriction base="xs:int">
      <xs:assertion test="$value mod 2 = 0" />
    </xs:restriction>
  </xs:simpleType>

(i.e, we need to use the XPath "dynamic context" variable, $value to access the XSD simple type value.)

If an attempt is made to access the XPath context in above XPath expression, like say as follows (using the expression, "." here):
<xs:assertion test=". mod 2 = 0" />

Xerces returns an error message like, following:
test.xml:4:21:cvc-assertion.4.3.15.3: Assertion evaluation ('. mod 2 = 0') for element 'x (attribute => a)' with type '#anonymous' did not succeed (undefined context).

Or an XPath expression, like following:
./@a mod 2 = 0

Would result in a similar error.

A special error message, was constructed (designating, "undefined context" to the user) in Xerces, for this use case.

2) Ability to evaluate assertions, on XML attributes

If attributes in XML document use user-defined XSD simple types, then assertions would also apply to attributes, as they do for XML elements.

Following is a little example for this, use case.

XML document:
  <Example>
    <x a="210">101</x>
  </Example>

Corresponding XSD 1.1 schema:
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    
    <xs:element name="Example">
       <xs:complexType>
         <xs:sequence>
           <xs:element name="x" type="X_Type" maxOccurs="unbounded" />
         </xs:sequence>
       </xs:complexType>
    </xs:element>
 
    <xs:complexType name="X_Type">
       <xs:simpleContent>
          <xs:extension base="xs:int">
             <xs:attribute name="a">
                <xs:simpleType>
                   <xs:restriction base="xs:int">
                     <xs:assertion test="$value mod 2 = 0" />
                   </xs:restriction>
                </xs:simpleType>
             </xs:attribute>
          </xs:extension>
       </xs:simpleContent>
     </xs:complexType>

  </xs:schema>

Please note, that how we specify a XSD user-defined simple type for attribute "a" above, and an assertion facet on the simple type (there could by 0-n assertion facets here, as we have been looking at earlier).

The assertion facet XPath expression, $value mod 2 = 0 would operate on the context variable, $value (which is the attribute's value) and such an assert facet doesn't have access to the XPath context (a "context undefined" error would be flagged by Xerces, if an attempt is made to access the XPath context).

I hope, that this post was useful.

No comments: