Using JAXP for Transformations
This API is described in the documentation provided with JDK 1.5 and later. It is available online at http://download.oracle.com/javase/6/docs/api/. Look for the javax.xml.transform package.
More information and examples relating to the JAXP transformation API can be found in
the JAXPExamples.java example application found in the samples
directory of the saxon-resources
file, see JAXP Transformation Examples.
If you want to be sure that Saxon (and not some other XSLT engine) is loaded to perform
your transformations, you need to know the class name of Saxon's implementation of the
JAXP TransformerFactory
class. This depends on which Saxon edition you are
using:
-
Any: net.sf.saxon.TransformerFactoryImpl. This will create a Saxon configuration based on the software and license file that are available at run-time on the classpath. For example, if the Saxon-PE software is on the classpath, and a license file for Saxon-PE is available, then the Saxon configuration will allow use of Saxon-PE capabilities such as extended serialization attributes. If you want to be sure of loading a configuration aligned with the features of a specific Saxon edition, use one of the more specific implementations of
TransformerFactory
. -
Saxon-HE: net.sf.saxon.BasicTransformerFactory
-
Saxon-PE: com.saxonica.config.ProfessionalTransformerFactory
-
Saxon-EE: com.saxonica.config.EnterpriseTransformerFactory
Saxon-EE with streaming: com.saxonica.config.StreamingTransformerFactory. This differs from the standard JAXP
TransformerFactory
in that the document supplied as theSource
argument of thetransform()
method does not cause the global context item to be set (any reference to the context item from the initializer of a global variable will therefore cause a dynamic error XPDY0002). When the source is supplied as aSAXSource
orStreamSource
and the initial mode is streamable, the transformation will run in streaming mode.The
newTransformerHandler()
method of theStreamingTransformerFactory
returns a SAXTransformerHandler
to which streamed input can be supplied as a sequence of calls on methods such asstartElement()
,characters()
, andendElement()
.Similarly, the
newXMLFilter()
method of theStreamingTransformerFactory
returns a SAXXMLFilter
which takes streamed input and produces streamed output; a fully streamed pipeline can be created by assembling a sequence of suchXMLFilter
classes in the usual JAXP way.
To ensure that the relevant implementation of TransformerFactory
is loaded,
several strategies are possible:
- Set the system property:
-Djava.xml.transform.TransformerFactory=net.sf.saxon.BasicTransformerFactory
- Use the version of
TransformerFactory.newInstance()
that accepts the name of the required factory class as a string. - Instantiate the class directly:
TransformerFactory factory = new net.sf.saxon.BasicTransformerFactory()
. This has the benefit of being much faster than the JAXP classpath search.
If your application uses this API in conjunction with other APIs such as the JAXP XPath
API or the JAXP Schema validation API, then you need to take care to ensure that all the
factory classes use the same underlying Saxon Configuration object. This is necessary to
ensure that the integer codes which Saxon uses internally for name matching
(NamePool
codes) are consistent. All the Saxon implementations of these
factory classes allow you to get and set the Configuration
so that you can
meet this requirement.
The types of object that can be supplied as stylesheet parameters are not defined in the
JAXP specification: they are implementation-dependent. Saxon takes the Java object
supplied, and converts it to an XPath value using the same rules as it applies for the
return value from a Java extension function: for these rules, see Saxon Extensibility. If the
resulting value is an atomic value, it is cast to the required type of the parameter as
specified in the xsl:param
declaration, using the XPath casting rules. If
the value is non-atomic (for example, if it is a node, or a sequence of integers), then
no conversion is attempted, instead, the value must match the required type as
stated.
The JAXP TransformerFactory
interface provides a configuration method
setAttribute()
for setting implementation-defined configuration
parameters. The parameters supported by Saxon have names defined by constants in the
class net.sf.saxon.lib.FeatureKeys.
The names of these properties and their meanings, are described in Configuration Features.
Where the required value of a property is a Boolean
, the supplied value may
be either a java.lang.Boolean
, or a string holding the values "true" or
"false" (also accepted are "on"|"off", "1"|"0", or "yes"|"no"). The returned value of
the property, however, will be a Boolean
.
From Saxon 9.6, Saxon's implementation of JAXP is layered on top of the s9api interface.
This means that attempts to "downcast" JAXP objects to the underlying Saxon objects (for
example, casting the JAXP Transformer
as an instance of
net.sf.saxon.Controller
) will no longer work. The Saxon implementation
classes are in most cases still available, but by a different route (for example the
Transformer
can now be cast to a
net.sf.saxon.jaxp.TransformerImpl
object, which offers a method
getUnderlyingController()
). But internal objects such as
net.sf.saxon.Controller
are not in general stable from one release to
the next.
When using the JAXP interface, you can set serialization properties using a
java.util.Properties
object. The names of the core XSLT 1.0 properties,
such as method
, encoding
, and indent
, are defined
in the JAXP class javax.xml.transform.OutputKeys
. Additional properties,
including Saxon extensions and XSLT 2.0/3.0 extensions, have names defined by constants in
the class net.sf.saxon.lib.SaxonOutputKeys. The values of the properties are exactly as
you would specify them in the xsl:output
declaration, except that QNames
are written in Clark notation ({uri}local
).