- Parsing XML Documents with DOM Level 2
- DOM Example: Representing an XML Document as a JTree
- Parsing XML Documents with SAX 2.0
- SAX Example 1: Printing the Outline of an XML Document
- SAX Example 2: Counting Book Orders
- Transforming XML with XSLT
- XSLT Example 1: XSLT Document Editor
- XSLT Example 2: Custom JSP Tag
- Summary
23.6 Transforming XML with XSLT
XSLT is a language for transforming XML documents into HTML, XML, or other types of documents. When performing a transformation, an XSLT engine converts the XML document according to formatting rules and XPath addresses specified in an XML style sheet (XSL). The XPath information identifies the different parts of the XML document for processing, and the style sheet information identifies the layout of the output.
The benefit of XSLT is that you can define multiple style sheets for transforming a single XML document. For example, a database could return a query in an XML format, and depending on the client protocol, HTTP or WAP, a servlet could use different style sheets to convert the data into HTML or WML, respectively. As another example of an XSLT application, consider an e-commerce business order; the order could be sent to the supplier in an XML format and then processed by the recipient with XSLT, using different XSL documents to convert the original order into separate billing and shipping documents.
Specifications for XSLT, XSL, and XPath technologies are maintained by the WWW Consortium. These specifications are located at:
XSLT 1.0
http://www.w3.org/TR/xslt.html
XSL 1.0
XPath 1.0
Upcoming specifications are summarized at http://www.w3.org/Style/XSL/. In addition, an excellent XSLT resource site, sponsored by GoXML, is located at http://www.xslt.com/.
Installation and Setup
XSLT is not a standard part of either Java 2 Standard Edition or the servlet and JSP APIs. So, your first step is to download the appropriate classes and configure them for use in your programs. Here is a summary of what is required:
Download an XSLT-compliant transformer. The transformer provides the Java classes that follow the XSLT 1.0 specification as specified by the WWW Consortium. You can obtain a list of XSLT parsers at http://www.w3.org/Style/XSL/ or 1. http://www.xslt.com/xslt_tools_engines.htm. We use the Apache Xalan-J transformer in this book. See http://xml.apache.org/xalan-j/.
Set your CLASSPATH to include the DOM and SAX classes. XSLT builds upon DOM and SAX for handling the document processing. In the case of Apache Xalan-J, you need to include xerces.jar in the CLASSPATH. See Section 23.1 (Parsing XML Documents with DOM Level 2) and Section 23.3 (Parsing XML Documents with SAX 2.0) for configuration of Apache Xerces-J. Note that xerces.jar is included in the Xalan-J installation directory.
Set your CLASSPATH to include the XSLT classes. With Xalan, these classes are in xalan_install_dir\xalan.jar. For example, for desktop application on Windows, you would do
set CLASSPATH=xalan_install_dir\xalan.jar; %CLASSPATH%
On Unix/Linux and the C shell, you would do
setenv CLASSPATH xalan_install_dir/xalan.jar: $CLASSPATH
If you wanted to use XSLT from servlets and JSP, you would copy the appropriate DOM, SAX, and XSLT JAR files to the server's lib directory (if supported), unpack the JAR files (using jar -xvf) into the server's classes directory, or explicitly change the server's CLASSPATH, usually by modifying the server's startup script.
-
Bookmark the XSL 1.0 and XPath 1.0 specifications. The official documentation for these two specifications can be found at http://www.w3.org/Style/XSL/.
-
Bookmark the XSLT specification. The official XSLT specification can be found at http://www.w3.org/TR/xslt.html. The XSLT specification is implemented in Apache Xalan through the Transformation API for XML (TrAX). The complete TrAX API comes with Xalan-J in Javadoc format and is also available on-line at http://xml.apache.org/xalan-j/apidocs/.
Translating
With XSLT processing, there are two high-level tasks, establishing an XSL template from which to build a transformer and invoking the transformer on the XML document. The following list summarizes the detailed steps needed to accomplish these tasks.
Tell the system which parser you want to use for transformations. This can be done in a number of ways: through the javax.xml.transform.TransformFactory system property, 1. through the jre_dir/lib/jaxp.properties, through the J2EE Services API and the class specified in the META-INF/services/ javax.xml.transform.TransformFactory, or with a system-dependent default processor. As XSLT depends on DOM and SAX, you can tell the system which DOM and SAX parser to use for processing the document. See Section 23.1 and Section 23.3 for information on configuring DOM and SAX parsers. By default, Apache Xalan-J uses the Apache Xerces-J DOM and SAX parsers.
Establish a factory in which to create transformers. Before processing an XML document, you first need to establish a TransformerFactory. The factory allows you to create different transformers for different style sheet templates.
TransformerFactory factory = TransformerFactory.newInstance();
Generate a transformer for a particular style sheet template. For each style sheet you can generate a separate transformer to apply to multiple XML documents.
Source xsl = new StreamSource(xslStream); Templates template = factory.newTemplates(xsl); Transformer transformer = template.newTransformer();
Typically, the XSL source is a StreamSource object. You can easily convert an XSL document to a StreamSource through a File, Reader, InputStream, or URI (represented as a string) reference to the document.
Invoke the transformer to process the source document. You invoke the transformation by calling the transform method, supplying the XML source and a Result object to receive the transformed document.
Source xml = new StreamSource(xmlStream); Result result = new StreamResult(outputStream); tranformer.transform(xml, result);
Similar to the XSL source, the XML source is typically a StreamSource constructed from a File, Reader, InputStream, or URI. The transformed StreamResult can be a File, Writer, OutputStream or URI.
Listing 23.12 presents a class for preforming XSLT transformations of documents. The XML and XSL source documents can be either Readers or Files, and the resulting transformed document can be a Writer or File. The advantage of handling the documents as Readers and Writers is that they can remain in memory and can easily be processed as strings by a StringReader or CharArrayReader for the source documents and a StringWriter or CharArrayWriter for the result document. For example, a servlet could receive a database query as an XML character stream, process the input using XSLT, and deliver the result as an HTML document to a browser client. At no time do the XML document and transformed result need to reside on disk.
Listing 23.12 XslTransformer.java
package cwp; import javax.xml.transform.*; import javax.xml.transform.stream.*; import java.io.*; import java.util.*; /** Creates an XSLT transformer for processing an XML document. * A new transformer, along with a style template are created * for each document transformation. The XSLT, DOM, and * SAX processors are based on system default parameters. */ public class XslTransformer { private TransformerFactory factory; public XslTransformer() { factory = TransformerFactory.newInstance(); } /** Transform an XML and XSL document as <code>Reader</code>s, * placing the resulting transformed document in a * <code>Writer</code>. Convenient for handling an XML * document as a String (<code>StringReader</code>) residing in memory, not on disk. The output document could easily be * handled as a String (<code>StringWriter</code>) or as a * <code>JSPWriter</code> in a JavaServer page. */ public void process(Reader xmlFile, Reader xslFile, Writer output) throws TransformerException { process(new StreamSource(xmlFile), new StreamSource(xslFile), new StreamResult(output)); } /** Transform an XML and XSL document as <code>File</code>s, * placing the resulting transformed document in a * <code>Writer</code>. The output document could easily * be handled as a String (<code>StringWriter</code)> or as * a <code>JSPWriter</code> in a JavaServer page. */ public void process(File xmlFile, File xslFile, Writer output) throws TransformerException { process(new StreamSource(xmlFile), new StreamSource(xslFile), new StreamResult(output)); } /** Transform an XML <code>File</code> based on an XSL * <code>File</code>, placing the resulting transformed * document in a <code>OutputStream</code>. Convenient for * handling the result as a <code>FileOutputStream</code> or * <code>ByteArrayOutputStream</code>. */ public void process(File xmlFile, File xslFile, OutputStream out) throws TransformerException { process(new StreamSource(xmlFile), new StreamSource(xslFile), new StreamResult(out)); } /** Transform an XML source using XSLT based on a new template * for the source XSL document. The resulting transformed * document is placed in the passed in <code>Result</code> * object. */ public void process(Source xml, Source xsl, Result result) throws TransformerException { try { Templates template = factory.newTemplates(xsl); Transformer transformer = template.newTransformer(); transformer.transform(xml, result); } catch(TransformerConfigurationException tce) { throw new TransformerException( tce.getMessageAndLocation()); } catch (TransformerException te) { throw new TransformerException( te.getMessageAndLocation()); } } }