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.

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:

To ensure that the relevant implementation of TransformerFactory is loaded, several strategies are possible:

  1. Set the system property: -Djava.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl
  2. Use the version of TransformerFactory.newInstance() that accepts the name of the required factory class as a string
  3. Instantiate the class directly: TransformerFactory factory = new net.sf.saxon.TransformerFactoryImpl(). 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.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 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).