System Programming Interfaces

In a number of internal interfaces, namespace URIs are now represented using the class NamespaceUri rather than String. NamespaceUri objects are pooled (so the same namespace is always represented by the same object), leading to fewer object allocations (and therefore less overhead in the garbage collector), and allowing more efficient comparison - equality testing is the dominant operation on namespace URIs.

Interfaces affected include NodeInfo, Receiver, StructuredQName, NodeName, XPathStaticContext, AttributeMap, and NamespaceMap. In some cases the old interface has been retained for compatibility, but use of a NamespaceUri is preferred.

The change may affect the handling of namespace URIs containing spaces (this is an area that has never been well defined in the W3C specifications, and is best avoided).

To convert a String to a NamespaceUri, use the static method NamespaceUri.of(String). For the reverse, use NamespaceUri.toString().

For SaxonJ, the Java system property SAXON_INITIALIZER may be set to the name of a class that implements net.sf.saxon.lib.Initializer. If the class can be loaded, it will be called during instantiation of a new Configuration. This makes it easier to customize Saxon's behavior when Saxon is deeply embedded in an application over which the user has no direct control. (Note, applications wishing to suppress this are free to clear the system property.)

Most warning conditions now have specific error codes associated with them, and internal interfaces have been extended so the error code can get through to a user-supplied ErrorReporter. This makes it much easier to suppress warnings selectively. The codes used can be found in the JavaDoc for class net.sf.saxon.trans.SaxonErrorCode (or, of course, in the warning message itself). The StandardErrorReporter now has a method suppressWarning that allows a specific warning condition to be suppressed.

The ParseOptions class is now immutable; any calls such as options.setValidationMode(V) must be replaced with options = options.withValidationMode(V). This change was made for performance reasons; we found that the code was spending a great deal of time creating and copying new ParseOptions objects.

A potential problem that has existed for many years, but which rarely surfaces, arises when a SequenceIterator holds external resources (for example an UnparsedTextLines iterator, which keeps a text file open), and the iterator is neither read to completion, nor explicitly closed. This typically occurs as a consequence of lazy evaluation. When such an iterator is created, Saxon now uses a Java Cleaner thread (owned by the Configuration) to close the relevant resources as soon as the iterator is garbage-collected. This extra thread may be visible in Java monitoring output. The thread shuts down when the Cleaner is garbage-collected, which typically happens when the Configuration is garbage collected; it can also be forced by calling Configuration.close().

Saxon's original XQuery API, in which a query is compiled using a StaticQueryContext object and executed using a DynamicQueryContext object, has been gradually downgraded over a number of releases. It remains present in the product, but should no longer be considered as a stable public API. The sample application QueryAPIExamples.java has now been dropped from the release.