System Programming Interfaces
The behavior of configuration.buildDocument()
has changed for cases where the supplied Source
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.)
The class 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 StaticContext
interface.
As part of the above change, some methods on StaticQueryContext
have been dropped. This notably includes
the method 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
Configurations.
The rule that all documents used within a single query, transformation, or XPath expression must be built using the
same 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 NamePool
and DocumentNumberAllocator
.
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 doc()
or 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
the 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 Configuration.setConfigurationProperty()
\
or TransformerFactory.setAttribute()
with the property name FeatureKeys.PRE_EVALUATE_DOC_FUNCTION
.
This option is not available from the command line because it has no useful effect with a single-shot
compile-and-run interface.
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.
In the 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.
The method NodeInfo#sendNamespaceDeclarations
has been deleted.
The class 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 iterateAxis()
.
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 ConversionResult
which is essentially a union type of AtomicValue
and ValidationFailure
. Code calling these
methods therefore has to consciously cast the result to AtomicValue
, preferably after checking that the
result is not a ValidationFailure
.
The two exception classes StaticError
and 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 StaticError
or DynamicError
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.