Reviews : Java Books : Java and XSLT :


Title: Java and XSLT
ISBN: 0-596-00143-6, Order Number: 143-6
US Price: $39.95
© O'Reilly & Associates, Inc.

SAXON Implementation

For comparison, a SAXON 5.5.1 implementation is presented in Example 5-2. As you scan through the code, you will notice the word "trax" appearing in the Java packages. This is an indication that Version 5.5.1 of SAXON was moving towards something called Transformation API for XML (TrAX). More information on TrAX is coming up in the JAXP discussion. In a nutshell, TrAX provides a uniform API that should work with any XSLT processor.

Example 5-2: SimpleSaxon.java

package chap5;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import org.xml.sax.SAXException;

/**
 * A simple demo of SAXON. This code was originally written 
 * using SAXON 5.5.1.
 */
public class SimpleSaxon {

/**
 * Accept two command line arguments: the name of an XML file, 
 * and the name of an XSLT stylesheet. The result of the 
 * transformation is written to stdout.
 */
public static void main(String[] args)
     throws MalformedURLException, IOException, SAXException {
    if (args.length != 2) {
     System.err.println("Usage:");
     System.err.println("  java " + SimpleSaxon.class.getName(  )
                + " xmlFileName xsltFileName");
     System.exit(1);
    }

    String xmlFileName = args[0];
    String xsltFileName = args[1];

    String xmlSystemId = 
	 new File(xmlFileName).toURL().toExternalForm(  );
    String xsltSystemId = 
	 new File(xsltFileName).toURL().toExternalForm(  );

    com.icl.saxon.trax.Processor processor =
            com.icl.saxon.trax.Processor.newInstance("xslt");

    // unlike Xalan, SAXON uses the SAX InputSource.  Xalan
    // uses its own class, XSLTInputSource
    org.xml.sax.InputSource xmlInputSource =
            new org.xml.sax.InputSource(xmlSystemId);
    org.xml.sax.InputSource xsltInputSource =
            new org.xml.sax.InputSource(xsltSystemId);

    com.icl.saxon.trax.Result result =
            new com.icl.saxon.trax.Result(System.out);

    // create a new compiled stylesheet
    com.icl.saxon.trax.Templates templates =
            processor.process(xsltInputSource);

    // create a transformer that can be used for 
		a single transformation
    com.icl.saxon.trax.Transformer trans = 
		templates.newTransformer(  );
    trans.transform(xmlInputSource, result);
  }
}
Note: Color coded lines were broken for display purposes only. In use they should appear on one line.

The SAXON implementation starts exactly as the Xalan implementation does. Following the class declaration, the command-line parameters are validated and then converted to system IDs. The XML and XSLT system IDs are then wrapped in org.xml.sax.InputSource objects as follows:

org.xml.sax.InputSource xmlInputSource =
        new org.xml.sax.InputSource(xmlSystemId);
org.xml.sax.InputSource xsltInputSource =
        new org.xml.sax.InputSource(xsltSystemId);

This code is virtually indistinguishable from the Xalan code, except Xalan uses XSLTInputSource instead of InputSource. As mentioned before, XSLTInputSource is merely a subclass of InputSource that adds support for reading from a DOM Node. SAXON also has the ability to read from a DOM node, although its approach is slightly different.

Creating a Result object sets up the destination for the XSLT result tree, which is directed to System.out in this example:

com.icl.saxon.trax.Result result =
        new com.icl.saxon.trax.Result(System.out);

The XSLT stylesheet is then compiled, resulting in an object that can be used repeatedly from many concurrent threads:

com.icl.saxon.trax.Templates templates =
        processor.process(xsltInputSource);

In a typical XML and XSLT web site, the XML data is generated dynamically, but the same stylesheets are used repeatedly. For instance, stylesheets generating common headers, footers, and navigation bars will be used by many pages. To maximize performance, you will want to process the stylesheets once and reuse the instances for many clients at the same time. For this reason, the thread safety that Templates offers is critical.

An instance of the Transformer class is then created to perform the actual transformation. Unlike the stylesheet itself, the transformer cannot be shared by many clients and is not thread-safe. If this was a servlet implementation, the Transformer instance would have to be created with each invocation of doGet or doPost. In our example, the code is as follows:

com.icl.saxon.trax.Transformer trans = 
	templates.newTransformer(  );
trans.transform(xmlInputSource, result);
Note: Color coded lines were broken for display purposes only. In use they should appear on one line.

SAXON, Xalan, or TrAX?

As the previous examples show, SAXON and Xalan have many similarities. While similarities make learning the various APIs easy, they do not result in portable code. If you write code directly against either of these interfaces, you lock yourself into that particular implementation unless you want to rewrite your application.

The other option is to write a facade around both processors, presenting a consistent interface that works with either processor behind the scenes. The only problem with this approach is that as new processors are introduced, you must update the implementation of your facade. It would be very difficult for one individual or organization to keep up with the rapidly changing world of XSLT processors.

But if the facade was an open standard and supported by a large enough user base, the people and organizations that write the XSLT processors would feel pressure to adhere to the common API, rather than the other way around. TrAX was initiated in early 2000 as an effort to define a consistent API to any XSLT processor. Since some of the key people behind TrAX were also responsible for implementing some of the major XSLT processors, it was quickly accepted that TrAX would be a de facto standard, much in the way that SAX is.

Stop by in one week for the next installment!

How to Add Java Applets to Your Site

New on the Java Boutique:

New Review:

Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling API boasts simplicity, ease-of-integration, a well-rounded feature set, and it's free!

New Applet:

Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA sequences into three useful formats.

Elsewhere on internet.com:

WebDeveloper Java
Lots of Java information on webdeveloper.com

WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.

ScriptSearch Java
Hundreds of free Java code files to download.

jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.