System Programming Interfaces
The behavior of
configuration.buildDocument() has changed for cases where the supplied
object is a tree. In particular, if it is a
DOMSource then the DOM Document node will normally be wrapped
in a Saxon wrapper object rather than being copied to a TinyTree. This has the effect of reinstating the pre-8.9
behaviour of methods in the XPath API that are given a DOMSource as an argument; the XPath expressions will now return
nodes in the original DOM tree rather than copies of these nodes.
Support for DOM Level 2 implementations has been reinstated; however Saxon no longer attempts to detect whether the
DOM supports level 3 interfaces; instead, when a Level 2 DOM implementation is used, the configuration setting
config.setDOMLevel(2) must be used. (Saxon now has compile-time references to DOM level 3 methods, but
will not call such methods if this configuration setting is in force.)
StaticQueryContext has been split into two: user-facing methods used to initialize the context
for a query are still in
StaticQueryContext, but methods intended for system use, which update the context
as declarations in the query prolog are parsed, have been moved to a new class
QueryModule. The class
StaticQueryContext no longer implements the
As part of the above change, some methods on
StaticQueryContext have been dropped. This notably includes
declareVariable() which never worked in a satisfactory way because the variable was not reusable
across multiple queries. External variables should always be declared from the query prolog.
A new factory method
Configuration.makeConfiguration() is available. This creates a schema-aware configuration
if Saxon-SA is installed and licensed, otherwise it creates a non-schema-aware configuration. This option is useful for
applications that want to take advantage of the enhanced Saxon-SA optimizer in cases where it is available, but do not
otherwise depend on Saxon-SA functionality.
A new method on
Configuration is introduced to copy a
Configuration. The main motivation for this
is to eliminate the high cost of repeatedly checking the Saxon-SA license key in applications that create many separate
The rule that all documents used within a single query, transformation, or XPath expression must be built using the
Configuration has been relaxed slightly, so the requirement is only that they must be "compatible" Configurations,
which means in practice that they must use the same
Although the rule has been
relaxed slightly, it is also now enforced on a number of interfaces where previously no checking took place (which could
lead to unpredictable failures later). This applies in particular to XPath APIs.
A new option is available in the
Configuration to indicate that calls to the
document() functions with constant string arguments should be evaluated when a query or
stylesheet is compiled, rather than at run-time. This option is intended for use when a reference or lookup
document is used by all queries and transformations. Using this option has a number of effects: (a) the
URI is resolved using the compile-time URIResolver rather than the run-time URIResolver; (b) the document
is loaded into a document pool held by the
Configuration, whose memory is released only when
Configuration itself ceases to exist; (c) all queries and transformations using this
document share the same copy; (d) any updates to the document that occur between compile-time and run-time
have no effect. The option is selected by using
TransformerFactory.setAttribute() with the property name
This option is not available from the command line because it has no useful effect with a single-shot
A convenience method
QueryResult.serialize(NodeInfo node) has been provided, allowing
a node to be serialized as XML; the result is returned as a String.
There is also a convenience method
Navigator.getAttributeValue(NodeInfo node, String uri, String localName)
making it easier for Java applications to get an attribute of an element.
NodeInfo interface, the rules for the
copy() method have changed so that
when an element is copied, its namespaces must be output without duplicates (or without a declaration being
cancelled by an undeclaration). The method no longer relies on the recipient removing such duplicates.
NodeInfo#sendNamespaceDeclarations has been deleted.
NameTest has a new constructor taking a URI and local name as strings, making it easier
to construct a
NameTest for use in calls to
iterateAxis(). In addition, the abstract class
NodeTest now has only one abstract method, making it easier to write a user-defined implementation of
NodeTest for filtering the nodes returned by
Methods that construct or convert atomic values no longer return ValidationErrorValue in the event of a failure.
There were a couple of problems with this mechanism: although it was designed to eliminate the costs of throwing an
exception, it failed to take into account the cost of creating the exception before throwing it, which is surprisingly
expensive as it involves capturing a stack trace. Secondly, the mechanism wasn't type safe as it didn't force callers to
check the return value for an error. These methods (and a number of others) now return a
which is essentially a union type of
ValidationFailure. Code calling these
methods therefore has to consciously cast the result to
AtomicValue, preferably after checking that the
result is not a
The two exception classes
DynamicError are no longer used: instead, their
common base class
XPathExpression is now a concrete class and is used to represent both static and dynamic
errors. It includes a field to distinguish the two cases, though in fact there is very little code that cares about the
difference (the only time the difference is significant is when dynamic errors occur during early compile-time evaluation
of constant subexpressions). Any application code that contains a catch for
should be changed to catch
XPathException instead. Since nearly all API methods declared "throws XPathException"
already, this is unlikely to be a major issue.
There has been some tidying up of methods on the
AtomicValue class, especially methods for converting
values between types and for setting the type label.