|
| |
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.
|
| | | | 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.
|
| |
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.
|
| | | | 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.
|
|
|