Orbeon Forms User Guide

XSLT and JAXP (TrAX) Processors

1. Introduction

XSLT 1.0 and XSLT 2.0 are languages for transforming XML documents into other XML documents. Orbeon Forms uses XSLT extensively to process XML documents.

Orbeon Forms ships with multiple implementations of XSLT:

  • Saxon 8.8 (supports XSLT 2.0 and XPath 2.0 in addition to XSLT 1.0 and XPath 1.0)
  • Saxon 6.5.2 (supports XSLT 1.0)
  • Xalan 2.5.1 Interpreter (supports XSLT 1.0)
  • Xalan 2.5.1 Compiler (XSLTC) (supports XSLT 1.0)

Additionally, Orbeon Forms can use any Java API for XML Processing (JAXP) compliant transformer.

2. Inputs and Outputs

Type Name Purpose Mandatory
Input transformer Specifies a concrete TransformerFactory class name. Yes
Implicit with concrete processors.
Input attributes Allows setting JAXP TransformerFactory attributes. No
Implicit with oxf:saxon8, oxf:unsafe-saxon8, oxf:xslt, oxf:unsafe-xslt
Input config The description of the transformation, typically an XSLT stylesheet. Yes
Input data The document to which the stylesheet is applied. Yes
Input User-defined inputs User-defined inputs accessible with the XPath document() or doc() functions. No
Output data The result of the transformation. Yes

3. Processor Names

There are three generic processors: a generic JAXP (TrAX) processor, and two specialized XSLT processors (one for XSLT 1.0 and one for XSLT 2.0), which provides additional functionality related to XSLT:

Processor Name Language Implementation
oxf:generic-xslt-1.0 XSLT 1.0 Generic JAXP (TrAX) XSLT 1.0 transformer (configure with transformer input)
oxf:generic-xslt-2.0 XSLT 2.0 Generic JAXP (TrAX) XSLT 2.0 transformer (configure with transformer input)
oxf:trax Any Generic JAXP (TrAX) transformer (configure with transformer input)

You usually don't use directly the generic processors. Instead, you use concrete processors that leverage the generic processors:

Processor Name Language Implementation
oxf:xslt XSLT 1.0 and 2.0 Saxon 8.8 with external functions disabled
oxf:unsafe-xslt XSLT 1.0 and 2.0 Saxon 8.8 with external functions enabled
oxf:xalan XSLT 1.0 Xalan 2.5.1 Interpreter
oxf:xsltc XSLT 1.0 Xalan 2.5.1 Compiler
oxf:saxon XSLT 1.0 Saxon 6.5.2
oxf:saxon8 XSLT 1.0 and 2.0 Saxon 8.8 with external functions disabled
oxf:unsafe-saxon8 XSLT 1.0 and 2.0 Saxon 8.8 with external functions enabled
oxf:xslt-1.0 XSLT 1.0 Default JAXP (TrAX) XSLT 1.0 transformer (currently Saxon 8)
oxf:xslt-2.0 XSLT 2.0 Default JAXP (TrAX) XSLT 2.0 transformer (currently Saxon 8)
oxf:pfc-xslt-1.0 XSLT 1.0 Default JAXP (TrAX) XSLT 1.0 transformer used by the Page Flow Controller (currently Saxon 8)
oxf:pfc-xslt-2.0 XSLT 2.0 Default JAXP (TrAX) XSLT 2.0 transformer used by the Page Flow Controller (currently Saxon 8)

The most commonly used processor is oxf:xslt, which provides excellent support for XSLT 1.0 and XSLT 2.0.

4. Usage

4.1. Transformer Input

The transformer input is mandatory only when using the generic processor: oxf:generic-xslt-1.0, oxf:generic-xslt-2.0 or oxf:trax. It is implied otherwise.

This input specifies a specific concrete subclass of TransformerFactory. For example, you can use the TrAX transformer to interface Orbeon Forms with a new hypothetical transformer (MyTrans):

<p:processor name="oxf:trax"><p:input name="transformer"><config><class>com.mytrans.TransformerFactoryImpl</class></config></p:input><p:input name="config"><mytrans>...</mytrans></p:input><p:input name="data"><document>...</document></p:input><p:output name="data" id="mytrans"/></p:processor>

4.2. Attributes Input

The attributes input is optional and is used to specify JAXP TransformerFactory attributes. It starts with a attributes element containing a number of attribute elements. Each element specifies a name, a type, and a value, all dependent on the actual transformer implementation. Saxon does not support the same attributes as Xalan, for example. The following types are supported:

  • xs:string: passed as a Java String
  • xs:integer: passed as a Java Integer
  • xs:boolean: passed as a Java Boolean
  • xs:date: passed as a Java Date
  • xs:dateTime: passed as a Java Date
  • xs:anyURI: passed as a Java URL

This is an example of configuration supported by Saxon:

<attributes xmlns:xs="http://www.w3.org/2001/XMLSchema"><attribute as="xs:boolean" name="http://saxon.sf.net/feature/allow-external-functions" value="false"/><attribute as="xs:boolean" name="http://saxon.sf.net/feature/linenumbering" value="false"/><attribute as="xs:integer" name="http://saxon.sf.net/feature/recoveryPolicy" value="2"/></attributes>

The attributes input is implicit with oxf:saxon8, oxf:unsafe-saxon8, oxf:xslt, oxf:unsafe-xslt.

4.3. Config Input

The config input contains a transformation, typically an XSLT stylesheet. The following example shows a simple XSLT stylesheet:

<xsl:stylesheet version="1.0"><xsl:template match="/"><new-root><xsl:value-of select="/root/a"/><xsl:value-of select="/root/b"/></new-root></xsl:template></xsl:stylesheet>

4.4. Data Input

The data input contains the source XML document. The example below works with the stylesheet shown above:

<root><a>a</a><b>b</b></root>

4.5. Data Output

The data output produces the result of the transformation. The following XML is the result of the above transformation:

<new-root>ab</new-root>

4.6. User-Defined Inputs

XSLT transformers support reading optional user-defined inputs through the XSLT and XPath document() and doc() functions. For example:

<p:processor name="oxf:xslt"><p:input name="config"><address-book xsl:version="2.0"><!-- Access external XML document --><xsl:variable name="document-1" select="doc('file:/document-1.xml')"/><!-- Access oxf:xslt processor user-defined input --><xsl:variable name="document-2" select="doc('input:my-input')"/><!-- ... --></address-book></p:input><!-- Standard oxf:xslt processor input --><p:input name="data" href="#some-id"/><!-- Declare oxf:xslt processor user-defined input --><p:input name="my-input" href="#some-other-id"/><!-- Standard oxf:xslt processor output --><p:output name="data" id="address-book"/></p:processor>

In this example, the XPath expression doc('file:/document-1.xml') instructs the XSLT transformer to read the document stored at oxf:/document-1.xml and make it accessible through the variable named document-1. This is standard XSLT and XPath 2.0.

The second variable, document-2, is assigned using a similar XPath expression, but it uses a URI with a particular syntax: it starts with the scheme input:. This instructs the XSLT transformer to read the processor input called my-input. This input is connected to the XSLT processor with <p:input name="my-input" href="#some-other-id"/>. In this case, it is up to the user of the XSLT processor to connect additional inputs as she sees fit, as long as their names don't conflit with mandatory input and output names.

Note

The user-defined input referenced from doc('input:my-input') must be declared as an input on the oxf:xslt processor, as shown above. If you wish to access a pipeline input using the doc() function, then you must first connect the pipeline input to the oxf:xslt processor input. For example:

<p:pipeline><!-- Pipeline input --><p:input name="my-pipeline-input" type="input"/><!-- XSLT transformation --><p:processor name="oxf:xslt"><p:input name="config"><address-book xsl:version="2.0"><!-- Access oxf:xslt processor user-defined input --><xsl:variable name="document-2" select="doc('input:my-input')"/><!-- ... --></address-book></p:input><!-- Standard oxf:xslt processor input --><p:input name="data" href="#some-id"/><!-- Connect the oxf:xslt processor input to the pipeline input --><p:input name="my-input" href="#my-pipeline-input"/><!-- Standard oxf:xslt processor output --><p:output name="data" id="address-book"/></p:processor><!-- ... --></p:pipeline>

5. Passing Parameters to XSLT Stylesheets

XSLT supports xsl:param elements at the top level of a stylesheet. They allow passing parameters to the stylesheet, without modifying the stylesheet itself. With API such as JAXP, a programmer can associate values to those parameters, making them available to the stylesheet during execution.

XPL does not have a particular mechanism to set such stylesheet parameters, but a simple workaround allows setting them. Assume you have a stylesheet with a start parameter, in a file called my-stylesheet.xsl:

<xsl:transform><xsl:param name="start" select="'a1'"/><!-- ... --></xsl:transform>

To set the start parameter with XPL, simply encapsulate the my-stylesheet.xsl stylesheet as follows:

<p:processor name="oxf:xslt"><p:input name="data" href="#stylesheet-input"/><p:input name="config"><xsl:stylesheet version="2.0"><xsl:import href="my-stylesheet.xsl"/><xsl:param name="start" select="'a2'"/></xsl:stylesheet></p:input><p:output name="data" id="stylesheet-output"/></p:processor>

The rules of XSLT's import statement will make sure that the imported stylesheet, my-stylesheet.xsl, receives the start parameter with the value "a2", as overridden in the importing stylesheet. Of course, the value does not have to be static, it can be computed dynamically as well.

Also note that while XPL does not have a native mechanism to pass XSLT parameters, it has a mechanism to pass extra documents available through the doc() function and the input: protocol. See User-Defined Inputs for more information.

6. Streaming Transformations for XML (STX)

Streaming Transformations for XML (STX) is a one-pass transformation language for XML documents that builds on the Simple API for XML (SAX). STX is intended as a high-speed, low memory consumption alternative to XSLT. Since it does not require the construction of an in-memory tree, it is suitable for use in resource constrained scenarios.

Orbeon Forms uses Joost to implement a STX transformer. Its usage is similar to an XSLT transformer, using the processor URI oxf:stx. This example demonstrates a simple STX transformation.

<p:processor name="oxf:stx"><p:input name="data" href="#source"/><p:input name="config"><stx:transform version="1.0" pass-through="all" strip-space="yes" xmlns:stx="http://stx.sourceforge.net/2002/ns"></stx:transform></p:input><p:input name="data" href="#document"/><p:output name="data" id="result"/></p:processor>