Next page Previous page Start of chapter End of chapter

Transformations

JAXP supports XSLT with packages javax.xml.transform and subpackages. A transformation operates on a source and obtains a result. Both source and result can be of three types:

Actually, the transform package can be exploited in two ways: to transform the representation of the same XML document from one form (such as SAX) to another (such as DOM), or, to transform the content of an XML document using an XSLT stylesheet. In both cases, the following steps must be followed:

  1. create a transformer factory:
    TransformerFactory factory = TransformerFactory.newInstance();
    
  2. get a transformer for the stylesheet:
    Transformer transformer = factory.newTransformer(stylesheet);
    
    where stylesheet is an XSLT document (version 1.0) in some source form (stream, SAX, DOM). You may also get a transformer with no associated stylesheet in case you want to transform the same XML document from one data representation to another (identity transformation):
    Transformer transformer = factory.newTransformer();
    
  3. possibly, set an error listener to customize warning and errors during transformation. An error listener is similar to an error handler and can be obtained by implementing the class ErrorListener:
    transformer.setErrorListener(handler);
  4. finally, perform the transformation from an input source to an output result:
    transformer.transform(input, output);

For example, the following program XMLTrans perform an XSLT transformation of an XML document into the standard output:

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class XMLTrans {
  
  static final String usage = 
      "Syntax: java XMLTrans document.xml stylesheet.xsl";

  public static void main(String[] args) {
    
    if (args.length != 2) {
      System.out.println(usage);
      System.exit(1);
    }
    
    // get source and result objects for input, stylesheet, and output
    StreamSource input = new StreamSource(new File(args[0]));
    StreamSource stylesheet = new StreamSource(new File(args[1]));
    StreamResult output = new StreamResult(System.out);
    /* or use:
    StreamResult output = new StreamResult(new File(filename));
    to save the result in a file
    */

    // create a transformer factory
    TransformerFactory factory = null;
    try {
      factory = TransformerFactory.newInstance();
    } catch (TransformerFactoryConfigurationError tfce) {
      // the implementation is not available or cannot be instantiated
      System.err.println(tfce.getMessage());
      System.exit(1);
    }
    
    // get a transformer for the stylesheet
    Transformer transformer = null;
    try {
      transformer = factory.newTransformer(stylesheet);
    } catch (TransformerConfigurationException tce) {
      // the transformer cannot be created
      System.err.println(tce.getMessage());
      System.exit(1);
    }
    
    // set an error listener
    transformer.setErrorListener(new TransHandler());
    
    // perform the transformation
    try {
      transformer.transform(input, output);
    } catch (TransformerException te) {
      // do nothing since an error handler has been installed
    }
  }
}

The error listener TransHandler is implemented as follows:

import javax.xml.transform.*;

/* Implements ErrorListener with methods to catch transformation warnings,
errors and fatal errors */
public class TransHandler implements ErrorListener {
    
  public String relativeSystemID(String id) {
    
    if (id != null) {
      int index = id.lastIndexOf('/');
      if (index != -1) {
        id = id.substring(index + 1);
      }
    }
    return id;
  }
  
  public void printError(String type, TransformerException te) {
    
    SourceLocator locator = te.getLocator();
    if (locator != null) {
      System.err.print("[" + type + "] ");
      System.err.print(relativeSystemID(locator.getSystemId()));
      System.err.print(":" + locator.getLineNumber() + 
                      ":" + locator.getColumnNumber() + 
                      ": " + te.getMessage());
    } else {
      System.err.print("[" + type + "] ");
      System.err.print(te.getMessageAndLocation());
    }
    System.err.println();
    System.err.flush();
  }
  
  // A warning message. The program continues.
  public void warning(TransformerException te) throws TransformerException {
    printError("warning", te);
  }

  // A transformation error. The program decides to exit.
  public void error(TransformerException te) throws TransformerException {
    printError("error", te);
    System.exit(1);
  }
  
  // A transformation fatal error. The program must exit.
  public void fatalError(TransformerException te) throws TransformerException {
    printError("fatal error", te);
    System.exit(1);
  }
}

The following code uses an identity transformer to switch form different representations of the same XML document. First, an XML file is read into a SAX source. The SAX source is then converted into a DOM result, which is finally transformed into a stream of XML text. The final result is not surprising: the input document is simply printed on the standard output. However, the code is interesting because it teaches how to use transformations to move between different forms of the same document:

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.sax.*;
import org.xml.sax.*;
import org.w3c.dom.*;

public class XMLTrans2 {
  
  public static void main(String[] args) throws TransformerException {
    
    // create an identity transformer
    TransformerFactory factory = TransformerFactory.newInstance();
    Transformer transformer = factory.newTransformer();
    
    // create a SAX source from an XML document
    SAXSource saxInput = new SAXSource(new InputSource(args[0]));
    
    // create a DOM result
    DOMResult domOutput = new DOMResult();

    // transform SAX representation into DOM representation
    transformer.transform(saxInput, domOutput);
    
    // obtain the document node of the DOM result
    Document document = (Document) domOutput.getNode();
    
    // create a DOM source from a node
    DOMSource domInput = new DOMSource(document);
        
    // create a stream result (the standard output)
    StreamResult streamOutput = new StreamResult(System.out); 
    
    // transform DOM representation into stream representation
    transformer.transform(domInput, streamOutput);
    
  }
}
Next page Previous page Start of chapter End of chapter
Caffè XML - Massimo Franceschet