W3C home > Mailing lists > Public > xmlschema-dev@w3.org > June 2007

[ANN] xchecker - XPath 2.0 embedded in XML Schema

From: Andrew Welch <andrew.j.welch@gmail.com>
Date: Tue, 5 Jun 2007 16:44:39 +0100
Message-ID: <74a894af0706050844x5f982017hb9dda16c4ecc295@mail.gmail.com>
To: xmlschema-dev@w3.org

xchecker is a little utility I've written that (amongst other things)
allows you to embed XPath 2.0 in XML Schema.

http://xchecker.sf.net/

The xchecker processor implements the JAXP schema interfaces, using
the underlying JAXP schema processor to do the validation.

You can check anything you can you can write an XPath for. For
example, if you had the XML:

<c:stock xmlns:c="http://company.com">
  <c:item id="001" price="1.50" quantity="6" total="9.00"/>
  <c:item id="002" price="2" quantity="0"/>
  <c:item id="003" price="3" quantity="1" total="3"/>
</c:stock>

...and you wanted to ensure only items with a quantity > 0 had a total
attribute, and that the total was correct, you could use:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xck="http://xchecker.sf.net/"
  targetNamespace="http://company.com"
  xmlns:c="http://company.com">

  <!-- The xchecker XPath checks can be used in <xs:appinfo> elements.
 The context node is the root node, all XPaths are global. -->
 <xs:annotation>
  <xs:appinfo>
   <!-- Check that all <c:item>'s with quantity greater than zero also
have a @total (by inverting it and checking that there doesn't exist a
<c:item> with a @quantity of zero and a total) -->
   <xck:check>not(exists(//c:item[number(@quantity) eq 0][@total]))</xck:check>

   <!-- Check that the @quantity is always correct (price * quantity)
and report a helpful message if it isn't -->
   <xck:check>for $x in //c:item[@total] return
	                if ($x[number(@total) ne @price * @quantity])
                          then
                            concat('Item ', $x/@id, ' has an incorrect total')
                          else
                            'true'</xck:check>

  </xs:appinfo>
 </xs:annotation>

 <xs:element name="stock">
   <xs:complexType>
     <xs:sequence>
       <xs:element ref="c:item" maxOccurs="3"/>
     </xs:sequence>
   </xs:complexType>
 </xs:element>

 <xs:element name="item">
    <xs:complexType>
     <xs:attribute name="id" type="xs:string" use="required"/>
     <xs:attribute name="price" type="xs:decimal" use="required"/>
     <xs:attribute name="quantity" type="xs:nonNegativeInteger" use="required"/>
     <xs:attribute name="total" type="xs:decimal"/>
   </xs:complexType>
 </xs:element>
</xs:schema>

To apply this schema from JAXP, create an XCheckerSchemaFactory and go
from there:

SchemaFactory schemaFactory = new XCheckerSchemaFactory();
Schema schema = schemaFactory.newSchema(xsd);
Validator validator = schema.newValidator();
validator.validate(new StreamSource(xml));

Saxon is used as the XPath engine, and as the preferred Schema
processor if its available.

More information is available at http://xchecker.sf.net/

cheers
andrew
Received on Tuesday, 5 June 2007 15:44:46 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Tuesday, 11 January 2011 00:14:59 GMT