Relationship of the processor to the Java API for XML Processing (JAXP)
In most cases, you will need to migrate any of your applications that used the Java™ API for XML Processing (JAXP) to use the current API.
The XSLT and XPath processing portions of JAXP are defined with reference to XSLT 1.0 and XPath 1.0. JAXP does not have provisions for XSLT 2.0 and XPath 2.0 processing. In particular, there are situations in which an XSLT 2.0 or an XPath 2.0 processor must produce a result that is different from that produced by an XSLT 1.0 or an XPath 1.0 processor given identical input and an identical stylesheet or expression. Therefore, it is not possible to instantiate the current processor using JAXP.
JAXP also does not have support for sequences, XQuery 1.0, or the many current data types that are available in XSLT 2.0, XPath 2.0, and XQuery 1.0. JAXP also is limited in the forms that input and output can take. All these things make it a poor fit for processing XSLT 2.0 stylesheets as well as XPath 2.0 and XQuery 1.0 expressions.
The following examples demonstrate common migration scenarios and how to write code using the current API that is equivalent to code that you might have written using JAXP.
Processing an XSLT stylesheet using the API
XFactory factory = XFactory.newInstance();
XSLTExecutable style = factory.prepareXSLT(new StreamSource("style.xsl"));
style.execute(new StreamSource("input.xml"), new StreamResult(System.out));
Processing an XPath expression using the API
XFactory factory = XFactory.newInstance();
XPathExecutable pathExpr = factory.prepareXPath("/doc/child[@id='N1378']");
// Process input from a StreamSource
XSequenceCursor result1 = pathExpr.execute(new StreamSource("input.xml"));
// Process input from a DOM node
XSequenceCursor result2 = pathExpr.execute(new DOMSource(node));
Resolving URI references
If you used instances of the JAXP URIResolver interface to resolve references to the XSLT document() function, you can now use the XSourceResolver interface to accomplish the same thing. To resolve references to the document() function or the fn:doc() function, you can set an instance of the XSourceResolver interface on an instance of the XDynamicContext interface; to resolve references to stylesheets imported through xsl:import and xsl:include declarations, you can set an instance of the XSourceResolver interface on an instance of the XStaticContext interface.
final XFactory factory = XFactory.newInstance();
XSLTExecutable style = factory.prepareXSLT(new StreamSource("style.xsl"));
XDynamicContext dContext = factory.newDynamicContext();
// Create and set an instance of an anonymous inner class as the
// XSourceResolver
dContext.setSourceResolver(new XSourceResolver() {
// Create an item to use as the initial context node for
// transformations in the getSource method
private XItemView fDummyNode =
factory.getItemFactory()
.item(new StreamSource(
new StringReader("<doc/>")));
// Resolve URIs by loading the resource as an XSLT stylesheet
// and evaluating it - return the result as the Source to use
public Source getSource(String href, String base) {
java.net.URI baseURI;
try {
// Get base URI object
baseURI = new java.net.URI(base);
} catch (java.net.URISyntaxException use) {
throw new RuntimeException(use);
}
// Resolved relative reference against base URI
String resolvedURI = baseURI.resolve(href).toString();
// Prepare and execute the stylesheet
XItemView transformResult =
factory.prepareXSLT(new StreamSource(resolvedURI))
.execute(fDummyNode);
return new XItemSource(transformResult);
}
});
XSequenceCursor result = style.execute(new StreamSource("input.xml"), dContext);
Defining extension functions and external functions
Using JAXP for XPath expression evaluation, you could register an instance of the XPathFunctionResolver interface to supply the implementations of extension functions that your XPath expressions might call. The XSLT portion of JAXP does not have an equivalent mechanism.
With the current API, you can declare extension functions on an instance of the XStaticContext interface, specifying the expected types of the arguments and the expected type of the result of calling the function, and you can register the implementations of extension functions on an instance of the XDynamicContext interface. Your XSLT stylesheet and XPath and XQuery expressions can call any extension functions that you register.
Setting the values of stylesheet parameters and external variables
Using JAXP, you could supply the initial values of stylesheet parameters by calling the Transformer.setParameter method and you could supply the values of variables for XPath expressions by supplying an instance of the XPathVariableResolver interface. Using the API, you can declare variables using the declareVariable() methods of the XStaticContext interface, specifying a variable name and the expected type of the variable. You can supply the values of stylesheet parameters, XPath variables, and XQuery external variables through one of the bind() methods of the XDynamicContext interface.
XFactory factory = XFactory.newInstance();
XStaticContext sContext = factory.newStaticContext();
// Declare the XPath variable "query-id" in the static context
QName queryIdVar = new QName("query-id");
sContext.declareVariable(queryIdVar, XTypeConstants.STRING_QNAME);
// Prepare the XPath expression
XItemFactory itemFactory = factory.getItemFactory();
XPathExecutable expr =
factory.prepareXPath("/catalog/product[id eq $query-id]", sContext);
XItemView catalog = itemFactory.item(new StreamSource("catalog.xml"));
XDynamicContext dContext = factory.newDynamicContext();
// Set the value of the "query-id" variable, and evaluate the
// expression with that variable value
dContext.bind(queryIdVar, "ID43785");
XSequenceCursor product1 = expr.execute(catalog, dContext);
// Set the value of the "query-id" variable, and evaluate the
// expression with the new variable value
dContext.bind(queryIdVar, "ID18574");
XSequenceCursor product2 = expr.execute(catalog, dContext);
Identity transformation
Another operation that is frequently used in JAXP is the identity transformation. This is a convenient way of transforming data from one form to another—for example, serializing a DOM tree, or producing a DOM tree from SAX events. It is possible to perform identity transformations using the API. See Performing basic XSLT operations for an example.
Prepare-time and execution-time configuration
In JAXP you supply much of the runtime configuration information for XSLT stylesheets – the values of stylesheet parameters, URIResolvers, and so on—directly on the objects that are used to perform transformations – instances of the Transformer interface and the TransformerHandler interface. Similarly, you supply configuration information for the preparation of stylesheets and XPath expressions directly on instances of the TransformerFactory and XPathFactory classes in JAXP.
With the API, you can supply configuration information that is needed at the time a stylesheet or an expression is prepared—namespace bindings, the types of external functions or variables, and so on—using an instance of the XStaticContext interface. Similarly, you can provide any configuration information that is needed to evaluate a stylesheet or expression—the values of variables, settings of output parameters, and so on—on an instance of the XDynamicContext interface, which you can pass as an argument to the execute methods of the XExecutable interface and its subinterfaces.
This separation of the configuration information into a separate object makes the API more thread safe. Your application can use the same instance of the XExecutable interface on different threads without any synchronization. This stands in contrast to JAXP, where instances of the Transformer, TransformerHandler and XPathExpression interfaces are not thread safe; every thread that uses them has to synchronize access to shared instances of those objects or create distinct copies that are specific to each thread.
Handling errors
In JAXP, you could supply an instance of the ErrorHandler interface to control how the processor should respond to errors. In the API, you can achieve this by supplying an instance of the XMessageHandler interface on an instance of the XStaticContext interface for preparation-time errors or the XDynamicContext interface for execution-time errors.