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.