SCDJWS Study Guide: JAXP


Printer-friendly version Printer-friendly version | Send this 
article to a friend Mail this to a friend


Previous Next vertical dots separating previous/next from contents/index/pdf Contents

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.

XSLT

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:

  1. Load the TransformerFactory factory with the static TransformerFactory.newInstance() factory method.
  2. Form a Source object from the XSLT stylesheet.
  3. Pass this Source object to the factory’s newTransformer() factory method to build a Transformer object.
  4. 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.
  5. Build a Result object for the target of the transformation. The Result object may be one of  DOMResult, SAXResult, and StreamResult object.
  6. 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:

  1. Establish  a TransformerFactory factory with the static TransformerFactory.newInstance() factory method. The factory allows  you to create different transformers for different style sheet templates.
  2. Form a Source object from the XSLT stylesheet.
  3. Pass this Source object to the TransformerFactory factory's newTemplates() factory method to create a Templates object.
  4. Use this Templates object's  newTransformer()  method to generate a Transformer object.
  5. Build a Source object from the input XML document you wish to transform.
  6. Build a Result object for the target of the transformation.
  7. 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).



Previous Next vertical dots separating previous/next from contents/index/pdf Contents

  |   |