Introduction Using a stylesheet file to transform an XML source file into an output file Using data streams in place of files Setting stylesheet parameters Compiling stylesheets Processing DOM input Producing DOM output Generating and responding to SAX events Working with XPath expressions Using the Xalan-Java applet wrapper Using Xalan-Java in a servlet Creating and using extensions Debugger interface
| Introduction |
| Xalan-Java takes as primary input an XML source document and an XSL stylesheet, both represented by instances of the XSLTInputSource class. You can use a URL or file, a character stream, a byte stream, a DOM tree, or a SAX input source to create an XSLTInputSource object. The stylesheet may also take the form of a compiled stylesheet (an instance of the StylesheetRoot class.
| If the XML document contains a stylesheet Processing Instruction (PI), Xalan-Java uses the stylesheet this PI points to and a separate stylesheet object is not required.
Xalan-Java uses an implementation of the XMLParserLiaison interface to interact with an XML parser and sends the output to XSLTResultTarget class, which may be configured to write to a file, a character stream, a byte stream, a DOM tree, or a SAX document handler. Unless your are reading or creating a DOM, you probably want to use the default DTM (Document Table Model) liaison and XML parser. When you read from a DOM or write to a DOM, use the XercesLiaison class along with the Xerces-Java XML parser. The XSLT and XPath engines are independent of any given XML parser implementation. All parser-dependent calls are funneled through the XMLParserLiaison. For detailed API documentation (javadoc), see API Documentation. For an overview of the command-line utility, see Command-Line Utility.
| Using a stylesheet file to transform an XML source file into an output file |
| Use an XML file and an XSL file to instantiate XSLTInput objects, create a processor, and write the transformation output to a file. For example:
    public static void Transform(String xmlSourceURL, String xslURL, String outputURL)
      throws java.io.IOException,
             java.net.MalformedURLException,
             org.xml.sax.SAXException
    {
      // Use XSLTProcessorFactory to instantiate an XSLTProcessor.
      org.apache.xalan.xslt.XSLTProcessor processor =
                     org.apache.xalan.xslt.XSLTProcessorFactory.getProcessor();

      // Create the 3 objects the XSLTProcessor needs to perform the transformation.
      org.apache.xalan.xslt.XSLTInputSource xmlSource =
                            new org.apache.xalan.xslt.XSLTInputSource ("foo.xml");
      org.apache.xalan.xslt.XSLTInputSource xslSheet =
                           new org.apache.xalan.xslt.XSLTInputSource ("foo.xsl");
      org.apache.xalan.xslt.XSLTResultTarget xmlResult =
                           new org.apache.xalan.xslt.XSLTResultTarget ("foo.out");

      // Perform the transformation.
      processor.process(xmlSource, xslSheet, xmlResult);
     }
You can perform this same transformation from the command line. For example: `java org.apache.xalan.xslt.Process -in foo.xml -xsl foo.xsl -out output.xml` For an online example, see SimpleTransform.
| Using data streams in place of files |
| The context in which you perform a transformation may call for input in the form of a character stream, byte stream, or SAX input stream, and output in the form of a character stream, byte stream, or SAX document handler. Suppose, for example, you want to output a stream of bytes for further processing:
    import org.apache.xalan.xslt.*;
    ...
    java.io.OutputStream byteStream = new java.io.ByteArrayOutputStream();
    XSLTResultTarget out = new XSLTResultTarget(byteStream)
    // Do the transformation...
    // Work with the OutputStream...
| Setting stylesheet parameters |
| An XSL stylesheet can include parameters that get set at run time when a transformation takes place. When we generate the HTML documents that make up the Xalan doc set, for example, we send the stylesheet an id parameter along with each XML source document. The id identifies that document and enables the stylesheet to integrate it into the overall doc set. To set a stylesheet parameter, use the XSLTProcessor setStylesheetParam(String key, String expression) method, where key is the parameter name and expression is an XPath expression. If the parameter is a String, enclose it in single quotes to make it a String expression. You can also use setStylesheetParam(String key, XObject value). This option is useful when you are working with the XPath API. For example, you could use the XObject returned by an Xpath function to set a parameter. You can include a -param argument when you call the command line utility.For example: `java org.apache.xalan.xslt.Process -in foo.xml -xsl foo.xsl -param param1 'boo'` The UseStylesheetParam sample application also uses a command-line parameter. For information about using stylesheet parameters with a compiled stylesheet, see the next section.
| Compiling stylesheets |
| A StylesheetRoot class object is a binary representation of a stylesheet that adds efficiency to the performance of repeated transformations and supports thread-safe concurrent access by multiple clients. If, for example, you are setting up a servlet to perform transformations, you can improve performance by compiling any stylesheets the servlet repeatedly uses. To compile a stylesheet, use one of the the XSLTProcessor interface processStylesheet methods. This operation also sets the XSLTProcessor Stylesheet property. In the interest of clarity, you may want to explicitly set that property. When you call the process method, include a null for the "uncompiled" stylesheet parameter so XSLTProcessor uses the compiled stylesheet. For example:
    import org.apache.xalan.xslt.*;
    ...
    XSLTProcessor processor = XSLTProcessorFactory.getProcessor();
    StylesheetRoot style = processor.processStylesheet
                                           (new XSLTInputSource("foo.xsl"));
    processor.setStylesheet(style); // Good form!
    ...
    processor.process(new XSLTInputSource("foo.xml"),
                      null, // Use the Stylesheet property setting.
                      new XSLTResultTarget("foo.out"));
Alternative: StylesheetRoot has its own process method, so another way to do the preceding is as follows:
    import org.apache.xalan.xslt.*;
    ..
    XSLTProcessor processor = XSLTProcessorFactory.getProcessor();
    StylesheetRoot style = processor.processStylesheet(new XSLTInputSource("foo.xsl"));
    ...
    style.process(new XSLTInputSource("foo.xml"), new XSLTResultTarget("foo.out"));
You should use the StylesheetRoot process(XSLTInputSource xmlIn, XSLTResultTarget xmlOut) method if you are using a StylesheetRoot object to transform multiple XML sources. The StylesheetRoot creates a new XSLTProcessor instance for each transformation. If you are using a compiled stylesheet to perform a transformation that includes a stylesheet parameter, use the version of the process() method that includes a parameter for the XSLTProcessor with which you have set the stylesheet parameter. Otherwise the parameter setting is not used. Keep in mind that you must reset the XSLTProcessor object if you want to use it in another transformation. For example:
    import org.apache.xalan.xslt.*;
    ...
    XSLTProcessor processor = XSLTProcessorFactory.getProcessor();
    processor.setStylesheetParam("param1", "'boo'");
    StylesheetRoot style = processor.processStylesheet
                                           (new XSLTInputSource("foo.xsl"));
    style.process (processor, new XSLTInputSource("foo.xml"),
                              new XSLTResultTarget("foo.out"));
    processor.reset();
    processor.setStylesheetParam("param1", "'foobar'");
    style.process (processor, new XSLTInputSource("bar.xml"),
                              new XSLTResultTarget("bar.out"));
If you want to use the XSLTProcessor as a SAX document handler, you must provide the processor a compiled stylesheet. See Generating and Responding to SAX events.
| Processing DOM input |
| The XML source and XSL stylesheet for a transformation may appear in the form of a DOM Node. To perform transformations with DOM input, you cannot use the default DTM (Document Table Model) liaison and parser. If you are processing DOM input, set up the XSLTProcessor to use XercesLiaison and the Xerces XML parser. The following code fragments illustrate the procedure for working with DOM input:
    import org.apache.xerces.parsers.DOMParser;
    import org.w3c.dom.Document;
    import org.apache.xalan.xpath.xdom.XercesLiaison;
    import org.apache.xalan.xslt.*;
    ...
    // Just in case you want to produce your own DOM input...
    DOMParser parser = new DOMParser();
    parser.parse("foo.xml");
    Document in = parser.getDocument();
    XSLTInputSource xmlID = new XSLTInputSource(in);

    // Set up the XSLTProcessor to use XercesLiaison.
    XSLTProcessor xsltProc = XSLTProcessorFactory.getProcessor
                     (new org.apache.xalan.xpath.xdom.XercesLiaison());
    // or you can use XSLTProcessorFactory.getProcessorUsingLiaisonName
    //                ("org.apache.xalan.xpath.xdom.XercesLiaison");
    ...
    // Perform the transformation.
| Producing DOM output |
| To produce a DOM Node as your transformation output, use a new Node to create the XSLTResultTarget for the transformation. Then when you perform the transformation, the result is output as a DOM Node. As with DOM input, you must set up the XSLTProcessor to use the Xerces liaison and XML parser. For example:
    import org.w3.dom.Document;
    import org.apache.xalan.xslt.*;
    ...
    XSLTProcessor xsltProc = XSLTProcessorFactory.getProcessor
                     (new org.apache.xalan.xpath.xdom.XercesLiaison());
    org.w3c.dom.Document out = new org.apache.xerces.dom.DocumentImpl();
    XSLTResultTarget resultTarget = new XSLTResultTarget(out);
    processor.process(new XSLTInputSource("foo.xml"),
                      new XSLTInputSource("foo.xsl"),
                      resultTarget);
The XSLTResultTarget object (resultTarget) now contains a Node. For a working example, see TransformToDom.
| Generating and responding to SAX events |
| To set up a transformation to generate SAX events, set the DocumentHandler property of the XSLTResultTarget object. The transformation consumer can then respond to these events as they occur, rather than waiting (as the consumer of a DOM must) for the complete result tree. This example sends the output to System.out.
    import org.apache.xalan.xslt.XSLTProcessor;
    import org.apache.xalan.xslt.XSLTInputSource;
    import org.apache.xalan.xslt.XSLTResultTarget;
    import org.apache.xalan.xslt.XSLTProcessorFactory;
    import org.apache.xalan.xslt.StylesheetRoot;

    public class TransformToSax
    {
    	public static void main(String[] args)
        throws java.io.IOException,
               java.net.MalformedURLException,
               org.xml.sax.SAXException
    	{
        XSLTProcessor processor = XSLTProcessorFactory.getProcessor();

        // Set the processor to use a compiled stylesheet.
        // The stylesheet provides access to a SAX DocumentHandler,
        // passing it the stylesheet xsl:output settings.
        StylesheetRoot stylesheet = processor.processStylesheet("foo.xsl");
        // This property was just set implicitly, but for good form...
        processor.setStylesheet(stylesheet);
        // In this case, send the output to System.out.
        org.xml.sax.DocumentHandler dh = stylesheet.getSAXSerializer(System.out);

        // Use the DocumentHandler to construct an XSLTResultTarget object.
        XSLTResultTarget saxResult = new XSLTResultTarget(dh);

        // Perform the transformation. The stylesheet parameter is null, so
        // the processor uses the compiled stylesheet identified by its
        // Stylesheet property setting.
        processor.process(new XSLTInputSource("foo.xml"), null, saxResult);
    	}
    }
XSLTProcessor also has a DocumentHandler property. By setting this property, you instruct the processor to process a sequence of SAX events. The processor needs a compiled stylesheet to perform this transformation. The following example uses the output of one transformation as the input for a second transformation. It does this by using two SAX DocumentHandlers to pipe SAX events from the first transformation to the second.
    import org.apache.xalan.xslt.*;

    public class ChainTransforms
    {
    	public static void main(String[] args)
        throws java.io.IOException,
               java.net.MalformedURLException,
               org.xml.sax.SAXException
    	{
        // Create processor for 1st transform.
        XSLTProcessor processor1 = XSLTProcessorFactory.getProcessor();

        // Create processor for 2nd transform. Set Stylesheet and
        // DocumentHandler properties so this processor uses the
        // 2nd stylesheet and processes SAX events (output from the
        // 1st transform), sending the final result to System.out.
        XSLTProcessor processor2 = XSLTProcessorFactory.getProcessor();
        StylesheetRoot stylesheet2 = processor2.processStylesheet("foo2.xsl");
        processor2.setStylesheet(stylesheet2);
        org.xml.sax.DocumentHandler dh = stylesheet2.getSAXSerializer(System.out);
        processor2.setDocumentHandler(dh);

        // Set up the 1st transform to produce a series of SAX events, and
        // to pass these events to the processor for the 2nd transform.
        // To accomplish this, create an XSLTResultTarget object for the
        // 1st transform, and use the processor for the 2nd transform to set
        // the XSLTResultTarget DocumentHandler property.
        XSLTResultTarget intermedResult = new XSLTResultTarget();
        intermedResult.setDocumentHandler(processor2);

        // Perform the 1st transform, which produces a series of
        // SAX events that are in turn processed by the processor2 DocumentHandler
        // in conjunction with stylesheet2, sending the output to System.out.
        processor1.process(new XSLTInputSource("foo.xml"),
                           new XSLTInputSource("foo.xsl"),
                           intermedResult);
    	}
    }
For a more compact (and elegant) form of this example, see the Pipe. For an example that uses SAX DocumentHandlers and the Xerces SAX parser to parse the XML input and XSL stylesheet and produce the transformation result, see the PureSAX.
| Working with XPath expressions |
| XSL stylesheets use XPath expressions to select nodes, specify conditions, and generate text for the result tree. XPath provides an API that you can call directly. For example, you may want to select nodes programmatically and do your own processing without a stylesheet. The XPathAPI class, in the samples/ApplyXPath subdirectory, contains several convenience methods that you can use to return single DOM Nodes, NodeLists, and XObjects. In the future, we plan to incorporate user feedback and move these methods into the core API. If you are interested in the API for executing XPath expressions, we suggest you take a look at the methods in XPathAPI, and send us feedback on what best meets your needs. For an example that uses the XPathAPI convenience methods to execute XPath expressions against XML source files, see ApplyXPath.
| Using the Xalan-Java applet wrapper |
| Include XSLTProcessorApplet class in an HTML client. Specify the XML source document and XSL stylesheet. You can use the DocumentURL and StyleURL PARAM tags or the XSLTProcessorApplet setDocumentURL() method and XSLTProcessorApplet setStyleURL() method. If the XML document contains a stylesheet Processing Instruction (PI), you do not need to specify an XSL stylesheet. Call the XSLTProcessorApplet transformToHTML() method which performs the transformation and returns the new document as a String. For an example, see the sample applet readme.
| Using Xalan-Java in a servlet |
| You can set up a servlet to use Xalan-Java to respond to requests for XML documents by transforming those documents into HTML and serving them to clients. For a sample of how this might be done, see sample servlet.
| Creating and using extensions |
| For those cases where you want to be able to call procedural code from within a stylesheet, the Xalan-Java Extensions facility supports the creation of extension elements and extension functions. See Extensions and Extensions samples.
| Debugger Interface |
| Xalan-Java contains a debugger interface in the org.apache.xalan.xslt.trace package: The TraceListener interface is an interface that debuggers can implement. The interface can be set on the XSLTProcessor interface by calling the addTraceListener function. The PrintTraceListener class is an implementation of the TraceListener interface. It is used by the command-line utility The TracerEvent class is an event that is passed to the TraceListener.trace function. It is called before a node is 'executed' in the stylesheet. The GenerateEvent class is an event that is passed to the TraceListener.generated() function. It is called after an event occurs to create something in the result tree. The SelectionEvent class is an event triggered by the selection of a give style tree node. The command-line utility uses the debugger interface when you include one or more of the following switches: -TT, -TG, -TS, -TTC. Example:
    import org.apache.xalan.xslt.XSLTProcessor;
    import org.apache.xalan.xslt.trace.PrintTraceListener;
    ...
    // Set up a PrintTraceListener object to print to a file.
    java.io.FileWriter fw = new java.io.FileWriter("events.log");
    java.io.PrintWriter pw = new java.io.PrintWriter(fw);
    PrintTraceListener ptl = new PrintTraceListener(pw);

    // Print information as each node is 'executed' in the stylesheet.
    ptl.m_traceElements = true;
    // Print information after each result-tree generation event.
    ptl.m_traceGeneration = true;
    // Print information after each selection event.
    ptl.m_traceSelection = true;
    // Print information whenever a template is invoked.
    ptl.m_traceTemplates = true;

    // Register the PrintTraceListener with the XSLTProcessor.
    XSLTProcessor processor = XSLTProcessorFactory.getProcessor();
    processor.addTraceListener(ptl);

    ...
    // Perform the transformation -- printing information to
    // events.log during the process.
    processor.process(new XSLTInputSource("foo.xml"),
                      new XSLTInputSource("foo.xsl"),
                      new XSLTResultTarget("foo.out"));
    ...
    // Close the PrintWriter and FileWriter.
    pw.close();
    fw.close();

Copyright © 2000 The Apache Software Foundation. All Rights Reserved.