Read XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition Online
Authors: Michael Kay
factory = TransformerFactory.newInstance();
by:
factory = new net.sf.saxon.TransformerFactoryImpl();
java -Djavax.xml.transform.TransformerFactory=
net.sf.saxon.TransformerFactoryImpl com.my-com.appl.Program
This all goes on one line. In practice of course you won't want to type this more than once, so create a batch file or shell script using your text editor, and invoke this instead.
System.setProperty (“javax.xml.transform.TransformerFactory”,
“net.sf.saxon.TransformerFactoryImpl”)
in your application, to be executed at runtime. This technique is useful if you want to run several different JAXP processors from the same application, perhaps in order to compare their results or to benchmark their performance.
TransformerFactory.newInstance(“net.sf.saxon.TransformerFactoryImpl”, null)
If you are still having trouble, try setting the Java system property
jaxp.debug
to
1
. This gives diagnostic information about the loading process.
The
TransformerFactory
interface in JAXP has a method
setAttribute()
, which allows processor-dependent configuration options to be set. Saxon offers a large number of such options, corresponding to all the options on the command line and a few more. Details are in the Saxon Javadoc documentation at
http://www.saxonica.com/documentation/javadoc/index.html
. The names of the attributes and a description of their purpose can be found in the specification of the class
net.sf.saxon.FeatureKeys
.
As well as accepting the standard three kinds of
Source
object defined in JAXP, that is,
StreamSource
,
SAXSource
, and
DOMSource
, a Saxon transformation can also take other kinds of input. Saxon's tree model uses an interface
net.sf.saxon.om.NodeInfo
to represent a node, and because this interface extends the JAXP
Source
interface, any
NodeInfo
can be used as the source of a transformation. If you want to use a document as input to several transformations, you can build the tree once using the factory method
Configuration.buildDocument()
, and then supply the returned
NodeInfo
to the Transformer's
transform()
method. You can also construct a
NodeInfo
as a wrapper around a DOM, JDOM, DOM4 J, or XOM document, and supply this wrapper to the transformer in the same way. As well as supplying the primary input to the transformation, all these techniques can be used to supply additional documents as the values of stylesheet parameters (just supply a
Source
as the argument to the Transformer's
setParameter()
method), or documents read using the
doc()
or
document()
functions (you can return any kind of
Source
from the user-supplied
URIResolver
).
The Schema Validation API
Saxon-SA supports the schema validation API defined in package
javax.xml.validation
. It provides an implementation of the
SchemaFactory
interface (
com.saxonica.jaxp.SchemaValidatorImpl
), which is currently in a separate package and JAR file for the benefit of JDK 1.4 users—this part of the JAXP API appears first in JDK 1.5. This allows you to load a schema, and to validate instance documents in either streaming (SAX) mode, or while building a DOM tree. Both these options are only really useful if you want to do freestanding validation.
Because the JAXP transformation API was designed for XSLT 1.0, it doesn't provide any direct way to request validation of the source document for a transformation, so Saxon provides its own mechanism. In fact, it provides several. One approach is to set a system-wide switch indicating that all source documents should be validated strictly or laxly. This can be done by calling
setAttribute(FeatureKeys.SCHEMA_VALIDATION, Validation.STRICT)
on the
TransformerFactory
object. If you want to control validation on a per-document basis, then you can create an
AugmentedSource
object with the appropriate options set.
AugmentedSource
is a JAXP Source object, so it can be used as input to a transformation, and as the name suggests it bundles together an underlying
Source
object with a number of parameters indicating how the source should be processed—one of these being an option to request schema validation.
Using XPath Expressions in Saxon
Another JAXP component introduced in JDK 1.5 is the interface for evaluating XPath expressions. Saxon implements this one too, allowing the source object to be either a native Saxon tree, or a DOM, JDOM, XOM, or DOM4 J tree wrapped in a Saxon
NodeInfo
wrapper.
Unfortunately the JAXP XPath API suffers a number of weaknesses. It is designed for XPath 1.0 rather than 2.0, which means it cannot handle the full range of data types that XPath 2.0 supports. I would therefore be strongly inclined to recommend using Saxon's s9api interface instead, which is described in the next section. There is also a legacy API in package
net.sf.saxon.sxpath
which you can use if you need it to work on JDK 1.4. This is modeled on the JAXP API, but has many differences of detail.
The s9api Interface
Saxon's s9api interface for Java was newly introduced in Saxon 9.0, strongly influenced by the success of the API provided on the .NET platform. The design aims were:
The starting point for an application is to create an instance of
Processor
(all classes are in package
net.sf.saxon.s9api
). This provides a few system-wide configuration options, acts as an owner of shared resources, and provides factory methods for other functionality.
Whether you are running XSLT, XQuery, or XPath, you follow the same sequence of steps:
1.
Create a compiler for the appropriate language, using one of the three factory methods
newXsltCompiler()
,
newXQueryCompiler()
, and
newXPathCompiler()
defined on the
Processor
class.
2.
Set properties on the compiler defining the static context for the compilation, and any other compile time options. For example, in the case of XPath this includes the base URI, the declared namespaces, and the external variables available to the XPath expression.
3.
Call the
compile()
method on the compiler. This creates a corresponding executable (
XsltExecutable
,
XQueryExecutable
, or
XPathExecutable
) which represents the compiled program or expression as an object in (potentially shared) memory. The principle in each case is that you only compile the object once, and you can run it as often as you like in the same thread or in different threads.
4.
Load the executable, by calling its
load()
method, which returns a runtime object called variously the
XsltTransformer
,
XQueryEvaluator
, or
XPathSelector
.
5.
Configure the runtime object by setting options that affect a single evaluation (that is, the dynamic evaluation context). This typically includes the node to be used as the initial context node, the runtime values of variables/parameters, and serialization options.
6.
Finally, run the transformation or query by calling one of the following methods:
The
Processor
also allows you to obtain a
DocumentBuilder
, which is used for building source documents in tree form, and a
SchemaManager
, which can be used to load schema documents into a central pool of schema definitions, which are then shared by all operations running under the control of the same
Processor
.
The s9api package includes a set of classes for representing objects defined in the XDM data model, and reflecting the XDM type hierarchy:
and these classes provide methods for converting between the XDM objects and native Java objects.
The result of a query or XPath expression can be returned as an
XdmValue
; alternatively, the relevant runtime objects implement the Java
Iterable
XPathCompiler compiler = processor.newXPathCompiler();
XPathSelector selector = compiler.compile(“//book[price > 20]”).load();
XDMNode doc = processor.newDocumentBuilder().build(new StreamSource(“in.xml”))
selector.setContextItem(doc);
for (XdmItem item : selector) {
System.out.println(“
}
The result of performing a transformation (or a validation) can be sent to any kind of
Destination
object. This is analogous to the JAXP
Result
object, except that it is possible to implement your own kinds of
Destination
. The system allows you to choose a number of possible destinations: