SCDJWS Study Guide: JAXP
Printer-friendly version |
Mail this to a friend
XSL Transformations
XSL Transformations (XSLT) is an API
that can be used to transform XML documents into other XML documents or
other formats such as HTML. A stylesheet written in the XML Stylesheet
Language (XSL) is usually needed to perform the transformation. The
stylesheet contains formatting instructions which specify how the
document is to be displayed.
The Extensible Stylesheet Language Transformations (XSLT) W3C
recommendation describes a transformation vocabulary used to specify
how to create new structured information from existing XML
documents.
The JAXP Transformation APIs include:
- javax.xml.transform
Defines the factory class TransformerFactory you use to get a Transformer object. You then configure the transformer with input (Source) and output (Result) objects, and invoke its transform() method to make the transformation happen. The source and result objects are created using classes from one of the other three packages.
- javax.xml.transform.dom
Defines the DOMSource and DOMResult classes that let you use a DOM as an input to or output from a transformation.
- javax.xml.transform.sax
Defines the SAXSource and SAXResult classes that let you use a SAX event generator as input to a transformation, or deliver SAX events as output to a SAX event processor.
- javax.xml.transform.stream
Defines the StreamSource and StreamResult classes that let you use an I/O stream as an input to or output from a transformation.
To transform an input document into an output document follow these
steps:
- Load the TransformerFactory factory
with the static TransformerFactory.newInstance()
factory method.
- Form a Source object from the XSLT stylesheet.
- Pass this Source object to the factory’s newTransformer() factory method to build a Transformer object.
- Build a Source object
from the input XML document you wish to transform. The Source object may be one of DOMSource,
SAXSource, and StreamSource object.
- Build a Result object for the target of the transformation. The Result object may be one of DOMResult, SAXResult, and StreamResult object.
- Pass both the source and the result to the Transformer object’s transform() method.
Steps four through six can be repeated for as many different input
documents as you want. You can reuse the same Transformer object repeatedly in
series, though you can’t use it in multiple threads in parallel because
neither TransformerFactory nor
Transformer is guaranteed to
be thread-safe. The following code is a sample code :
package com.xyzws.jaxp.xslt.sample;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
public class XSLTSample1 {
public static void main(String[] args) {
try {
TransformerFactory factory =
TransformerFactory.newInstance();
Source
xsl = new StreamSource("Sample1.xsl");
Transformer transformer = factory.newTransformer(xsl);
Source
request = new StreamSource("input.xml");
Result
response = new StreamResult("output.xml");
transformer.transform(request, response);
}
catch
(TransformerException e) {
System.err.println(e);
}
}
}
Neither TransformerFactory nor
Transformer is guaranteed to
be thread-safe. If your program is multi-threaded, the simplest
solution is just to give each separate thread its own TransformerFactory and Transformer objects. However, this
can be expensive, especially if you frequently reuse the same large
stylesheet, since it will need to be read from disk or the network and
parsed every time you create a new Transformer object. There is also
likely to be some overhead in building the processor’s internal
representation of an XSLT stylesheet from the parsed XML tree.
An alternative is to ask the TransformerFactory
to build a Templates object
instead. The Templates class
represents the parsed stylesheet. You can then ask the Templates class to give you as
many separate Transformer objects
as you need, each of which can be created very quickly by copying the
processor’s in-memory data structures rather than by reparsing the
entire stylesheet from disk or the network. The Templates class itself can be
safely used across multiple threads. To transform an input document
into an output document follow these steps:
- Establish a TransformerFactory
factory with the static TransformerFactory.newInstance()
factory method. The factory allows you to create different
transformers for different style sheet templates.
- Form a Source object from the XSLT stylesheet.
- Pass this Source object
to the TransformerFactory factory's
newTemplates() factory
method to create a Templates object.
- Use this Templates object's newTransformer() method to generate a Transformer object.
- Build a Source object from the input XML document you wish to transform.
- Build a Result object for the target of the transformation.
- Pass both the source and the result to the
Transformer object’s transform() method.
Steps four through seven can be repeated for as many different input
documents as you want. You create a separate thread-unsafe Transformer object in the step
four for each thread so the Transformer
object does not shared by multiple threads. All the
time-consuming work is done when the Templates
object is created. Calling templates.newTransformer()
is very quick by comparison. Here is a sample code using Templates object:
package com.xyzws.jaxp.xslt.sample;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
public class XSLTSample1 {
public static void main(String[] args) {
try {
TransformerFactory factory = TransformerFactory.newInstance();
Source
xsl = new StreamSource("Sample1.xsl");
Templates template = factory.newTemplates(xsl);
Transformer transformer = template.newTransformer();
Source
request = new StreamSource("input.xml");
Result
response = new StreamResult("output.xml");
transformer.transform(request, response);
}
catch
(TransformerException e) {
System.err.println(e);
}
}
}
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. 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.
Here is an example that takes a DOM object and transforms it into an XML document:
//create xsl
File xsltFile = new File(xsltFileName);
StreamSource xslSource = new StreamSource(xsltFile);
//create a new DOMSource using the root node of an existing DOM
tree
DOMSource source = new DOMSource(thePhonebook);
StreamResult result = new StreamResult(System.out);
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer(xslSource);
transformer.transform(source, result);
We first instantiate a new TransformerFactory
object by calling newInstance, which goes through the ordered
lookup
procedure (see "Simple
API for XML (SAX) ") to determine the Transformer
implementation to use. As with
SAX and DOM factories, there are
several settings that can be set which determine the way Transformer
objects are created. After a new transformer is created using
newTransformer, the transform method is then called, which takes
a
Source object (implemented by DOMSource, SAXSource,
and StreamSource) and
transforms it into the format of the Result object (implemented
by
DOMResult, SAXResult, and StreamResult).