| Questions |

- Where do I go to learn about XSLT
- Which version of Xerces should I be using?
- Are there any shortcuts for using a transformation result as input for another transformation?
- Are the XSLTProcessor and StylesheetRoot (compiled stylesheet) objects thread-safe?
- Why do XSLTProcessor and StylesheetRoot both have process() methods to perform transformations?
- What can I do to speed up transformations?
- I'm getting a NoClassDefFound error. What has to be on the class path?
- Stylesheet validation

| Answers |

| Where do I go to learn about XSLT? |

The definitive sources are the W3C XSLT and XPath recommendations: W3C Recommendation 16 November 1999 XSL Transformations (XSLT) Version 1.0 and XML Path Language (XPath) Version 1.0.

For general questions not specific to Xalan-Java, see Dave Pawson's XSL Frequently Asked Questions and Michael Kay's XSLT Programmer's Reference.

For a brief listing of tutorials, discussion forums, and other materials, see Getting up to speed with XSLT.

| Which version of Xerces should I be using? |

| The Xalan-Java release notes includes information about the Xerces release with which the Xalan-Java release has been coordinated and tested. See Status

| Are there any shortcuts for using a transformation result as input for another transformation? |

You can always get a transformation result from the XSLTResultTarget class object, and use it to set an XSLTInputSource class object for another transformation, but yes, there is a shortcut. Basically, you want to set up the XSLTResultTarget object that receives the output from the first transformation (performed with the XML source, the first stylesheet, and the first XSLTProcessor interface object) to function as a SAX DocumentHandler in conjunction with a second XSLTProcessor object that uses the second stylesheet and also functions as a DocumentHandler.

To walk through a brief example, see Generating and responding to SAX events.

| Are the XSLTProcessor and StylesheetRoot (compiled stylesheet) objects thread-safe? |

The XSLTProcessor stores running state information, so it is not thread-safe. If you want to use the XSLTProcessor to perform multiple transformations, create a new instance for each transformations or synchronize. If you want to perform multiple serial transformations with a single XSLTProcessor object, call the XSLTProcessor reset() method between each transformation.

StylesheetRoot objects, on the other hand, are thread-safe. A single StylesheetRoot object may be called concurrently from multiple threads.

For more information, see the next question.

| Why do XSLTProcessor and StylesheetRoot both have process() methods to perform transformations? |

To perform a transformation, Xalan-Java uses XML input, an XSL stylesheet, and XSLTProcessor. In one scenario, you use XSLTInputSource class objects as containers for the XML input and the XSL stylesheet. To perform the transformation, the XSLTProcessor interface object "compiles" the stylesheet, producing a StylesheetRoot class object, but you the user have no direct interaction with the StylesheetRoot.

Example:

    import org.apache.xalan.xslt.*;
        ...
        XSLTProcessor proc = XSLTProcessorFactory.getProcessor();
        proc.process(new XSLTInputSource("foo.xml"),
                     new XSLTInputSource("foo.xsl"),
                     new XSLTResultTarget("foo.out");

Second scenario: you want to perform a number of transformations with the same stylesheet. To improve performance, you compile the stylesheet once, and use the resulting StylesheetRoot class object for each transformation.

You can use the XSLTProcessor process() method with a compiled stylesheet. For an example, see Compiling stylesheets. But an XSLTProcessor object is not thread-safe and must be reset between transformations. A StylesheetRoot object, on the other hand, is thread-safe and may even be used concurrently (running in a servlet, for example) to perform multiple transformations, so it is more straightforward to use the StylesheetRoot process() method to perform the transformations.

Example:

    import org.apache.xalan.xslt.*;
          ...
          // Pass in an array of XML input file names and an
          // "uncompiled" stylesheet file name.
          public multiTransform(String[] xmlInputFiles, String xslFile)
          {
            XSLTProcessor proc = XSLTProcessor.Factory.getProcessor();
            StylesheetRoot style = proc.ProcessStylesheet
                                              (new XSLTInputSource(xslFile));
            for (int i = 0; i < xmlInputFiles.length; i++)
            {
              style.process(new XSLTInputSource(xmlInputFiles[i],
                            new XSLTResultTarget(xmlInputFiles[i] + ".out"));
            }
          }
          ...

| What can I do to speed up transformations? |

In the ongoing development of Xalan-Java, enhancing performance is the primary goal of the Xalan-Java team. Here are some preliminary suggestions for you to keep in mind as you set up your applications:

- Use the default DTM liaison and XML parser unless you need to read or write a DOM. DOM is expensive in terms of memory, and DOM and DOM2 do not include the interfaces required for optimal performance without the use of side tables.
- Set the XSLTProcessor to function as a SAX DocumentHandler, and respond to SAX events rather than waiting for the entire transformation to be completed.
- Use compiled stylesheets for multiple transformations.
- Set up your stylesheets to function efficiently.

- Don't use "//" (descendant axes) patterns near the root of a large document.
- Use xsl:key elements and the key() function as an efficient way to retrieve node sets.
- Where possible, use pattern matching rather than xsl:if or xsl:when statements.
- xsl:for-each is fast because it does not require pattern matching.
- Keep in mind that xsl:sort prevents incremental processing.
- When you create variables, <xsl:variable name="fooElem" select="foo"/> is usually faster than >xsl:variable name="fooElem"><xsl:value-of-select="foo"/></xsl:variable>.
- Be careful using the last() function.
- The use of index predicates within match patterns can be expensive.
- Decoding and encoding is expensive.

- For the ultimate in server-side scalability, perform transform operations on the client. For an example, see AppletXMLtoHTML.

| I'm getting a NoClassDefFound error. What has to be on the class path? |

1. xalan.jar xerces.jar must always be on the class path.
2. As a general rule, xerces.jar must be on the class path. If you have set up an extension of to work with another XML parser, all you need from xerces.jar are the serializers and the implementation of the SAX 2 interface.
3. To run the samples in the samples subdirectories, xalansamples.jar must be on the class path. To run the servlet (in samples/servlet), the javax.servlet and javax.servlet.http packages must also be on the class path. Sun distributes these packages in the JSWDK 1.0.1 servlet.jar file.
4. To run extensions (including the samples in samples/extensions), bsf.jar, and bsfengines.jar must be on the class path. To run extensions implemented in JavaScript, js.jar must also be on the class path. For information on what you need to run extensions implemented in other scripting languages, see Supported languages.

For more information, see Setting up the system class path.

| How do I validate an XSL stylesheet? |

An XSL stylesheet is an XML document, so it can have a DOCTYPE and be subject to validation, right?

The XSLT Recommendation includes a DTD Fragment for XSL Stylesheets with some indications of what you need to do to create a complete DTD for a given stylesheet. Keep in mind that stylesheets can include literal result elements and produce output that is not valid XML.

You can use the xsl:stylesheet doctype defined in xsl-html40s.dtd for stylesheets that generate HTML.

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