Using JAXP for Transformations

This API is described in the documentation provided with JDK 1.5 and later. It is available online at Look for the javax.xml.transform package.

More information and examples relating to the JAXP transformation API can be found in the 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 the Source argument of the transform() 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 a SAXSource or StreamSource and the initial mode is streamable, the transformation will run in streaming mode.

    The newTransformerHandler() method of the StreamingTransformerFactory returns a SAX TransformerHandler to which streamed input can be supplied as a sequence of calls on methods such as startElement(), characters(), and endElement().

    Similarly, the newXMLFilter() method of the StreamingTransformerFactory returns a SAX XMLFilter which takes streamed input and produces streamed output; a fully streamed pipeline can be created by assembling a sequence of such XMLFilter classes in the usual JAXP way.

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.BasicTransformerFactory
  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.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 following rules:

  • If the supplied value is a string, it is converted to an instance of xs:untypedAtomic (this means it can be further converted if, for example, the required type is xs:integer).

  • If the required type (defined by the xsl:param/@as attribute) is an "external Java object" type such as Q{}java.util.List, then the supplied Java object is wrapped and no further conversion is applied.

  • The JAXP interface does not allow the supplied value to be null. To bind the parameter to an empty sequence, supply an empty java.util.List.

  • In other cases, the conversion rules described at Converting Java values to XDM values are used.

  • The result of the previous steps is then converted, where necessary, to the declared type of the xsl:param element by applying the standard function conversion rules defined in the XPath specification: for example, if the supplied value is a node and the required value is a string, then the node will be atomized.

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.Feature. 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).