Saxonica.com

XQJ (XQuery API for Java)

Saxon's implementation of XQJ has been brought into line with the 1.0 "final draft" released on 20 Nov 2007. The final draft includes a set of compatibility tests, and Saxon now passes all these tests, with the exception of four tests whose results have been queried as they appear inconsistent with the documentation.

This change means that the XQJ interfaces now have their proper package names (javax.xml.query.* in place of net.sf.saxon.javax.xml.query.*, and applications will need to be updated accordingly. The interfaces together with the implementation classes are in the JAR file saxon9-xqj.jar .

To pass the test suite, quite a few changes were necessary, but few of these will affect applications. Many of them concern the error behaviour when null arguments are passed to methods, or when operations are attempted on a connection that has been closed - neither of which are things that real applications are likely to do.

One more noticeable change is that the rules for processing a forwards-only sequence are now strictly enforced. These rules prevent you accessing the same item in the result of a query more than once, unless you save a local copy using the getItem() method.

As required by the licensing conditions for XQJ, a conformance statement is provided.

The XQJ implementation now allows a Java object to be supplied as an "external object", whose instance methods can be invoked as external functions within the query. TestL in the sample application XQJExamples.java provides an illustration of how to do this. It is necessary to create an XQItemType representing the type of the item: this will always have a name whose URI is http://saxon.sf.net/java-type and whose local name is the qualified name of the Java class. The standard XQJ method createItemFromObject() will recognize a type name in this form and handle the object accordingly.

A number of named properties have been implemented to allow Saxon's behavior to be configured via the setProperty() method of XQDataSource; for details see the Javadoc of the Saxon implementation class SaxonXQDataSource. For configuration settings that are not in this list, SaxonXQDataSource provides a method getConfiguration() that allows access to the underlying Configuration object.

A Saxon-specific method has been added to the SaxonXQConnection class, which is Saxon's implementation of XQConnection. The method copyPreparedExpression() allows an XQPreparedExpression created under one connection to be copied to a different connection. This makes it much easier to compile a query once and run in concurrently in multiple threads, a facility that is notoriously absent from the XQJ specification. When a prepared expression is copied in this way, the compiled code of the query and the static context are shared between the two copies, but each copy has its own dynamic context (for query parameters and suchlike).

There have been changes to the implementation of XQJ methods involving input or delivery of results using the Stax XMLStreamReader interface. These methods are now implemented using the "pull events" mechanism introduced in Saxon 9.0, replacing the older PullProvider interface.

A new EventIterator is available for use in the event-pull pipeline, namely NamespaceMaintainer. This maintains the namespace context (it acts as a NamespaceResolver). This is used by XQJ when delivering results in the form of a StAX XMLStreamReader, underpinning the methods on the XMLStreamReader interface that allow namespace prefixes to be resolved.

Next