See also: Transform Features.
 |
Unless otherwise
specified, the usage discussed in this section refers to the
Xalan-Java Interpretive processor. See Getting Started Using XSLTC for
information on using the Xalan-Java Compiling
processor. |
 |
 |
 |
 |
3. Use the Transformer to perform a
transformation |
 |
 |
 |
 |
|
|
Use the
Transformer
transform(Source xmlSource, Result transformResult) method to
transform the XML Source and place the transformation output in a
Result object.
Just as
with the stylesheet, you can supply the XML Source in the form of a
StreamSource,
DOMSource, or
SAXSource. Likewise, the Result may be a
StreamResult,
DOMResult, or
SAXResult.
For each
node in the XML source, the Transformer uses the transformation
instructions in the Templates object to determine which template to
apply: one of the templates in the Templates object, a default
template rule as specified in the XSLT spec, or none.
|
 |
 |
 |
 |
Working with embedded
stylesheets |
 |
 |
 |
 |
|
|
An XML
Source may include an xml-stylesheet
processing instruction which identifies the stylesheet to be
used to process the document. As indicated by the processing
instruction href attribute, the stylesheet itself may be
embedded in the XML document or located elsewhere.
Suppose
you have an XML document (foo.xml) with the following
xml-stylesheet processing instruction:
<?xml-stylesheet type="text/xml"
href="foo.xsl"?>
The
following fragment, uses this instruction to locate the stylesheet
(foo.xsl in the same directory as foo.xml) and create a Templates
object. Note the use of the TransformerFactory
getAssociatedStylesheet() in step 2a.
 |
An XML document may
include more than one xml-stylesheet processing instruction, hence
the support for working with multiple stylesheets. If more than one
stylesheet is returned, the other stylesheets are imported into the
first stylesheet. |
 |
 |
 |
 |
// 1. Instantiate the TransformerFactory.
javax.xml.transform.TransformerFactory tFactory =
javax.xml.transform.TransformerFactory.newInstance();
// 2a. Get the stylesheet from the XML source.
String media = null , title = null, charset = null;
javax.xml.transform.Source stylesheet = tFactory.getAssociatedStylesheet
(new StreamSource("foo.xml"),media, title, charset);
// 2b. Process the stylesheet and generate a Transformer.
Transformer transformer = tFactory.newTransformer(stylesheet);
// 3. Use the Transformer to perform the transformation and send the
// the output to a Result object.
transformer.transform
(new javax.xml.transform.stream.StreamSource("foo.xml"),
new StreamResult (new java.io.FileOutputStream("foo.out")));
|
 |
 |
 |
 |
For a
sample that uses this technique, see UseStylesheetPI.
You can
also instruct the command-line
utility to use stylesheet processing instructions:
- Include
the
-in flag
with an XML source that contains a stylesheet processing
instruction.
- Do not
include the
-xsl flag.
|
|
|
In some
cases, you may want to "transform" a DOM tree into a stream, which
the XML community calls serialization. TRaX
(Transformation API for XML) and the Xalan-Java Transformer
implementation provide direct support for this operation. Simply
use the TransformerFactory newTransformer() method (no arguments)
to create a Transformer that you can use to "copy" a DOMSource to a
StreamResult. For examples, see Examples.exampleDOM2DOM(),
Examples.exampleSerializeNode(), and Examples.exampleAsSerializer()
in the trax sample.
|
 |
 |
 |
 |
Explicitly working with
SAX |
 |
 |
 |
 |
|
|
Xalan-Java
uses the SAX event model to process stylesheets, to parse XML input
documents, and to produce output. For each of these operations, an
XMLReader reads input, firing parse events, and a ContentHandler
listens to the XMLReader and executes parse event
methods.
When you
use the basic procedure described above for performing
transformations, Xalan-Java takes care of many of the SAX details
under the covers. You are free to make these details explicit,
which simply means that you can intervene in the procedure to
accommodate the precise environment in which your application
operates.
Suppose,
for example, you are using a custom XMLReader, perhaps doing more
than just parsing static XML documents) to generate Xalan-Java SAX
parse events. You might even have a custom reader for
producing/processing stylesheets. You can cast the
TransformerFactory to a SAXTransformerFactory, which provides
access to a TransformerHandler, which you can set as the
ContentHandler for this reader.
The
following example explicitly sets up the XMLReader and
ContentHandlers, and replicates the basic steps described
above.
 |
 |
 |
 |
// Instantiate a TransformerFactory.
javax.xml.transform.TransformerFactory tFactory =
javax.xml.transform.TransformerFactory.newInstance();
// Verify that the TransformerFactory implementation you are using
// supports SAX input and output (Xalan-Java does!).
if (tFactory.getFeature(javax.xml.transform.sax.SAXSource.FEATURE) &&
tFactory.getFeature(javax.xml.transform.sax.SAXResult.FEATURE))
{
// Cast the TransformerFactory to SAXTransformerFactory.
javax.xml.transform.sax.SAXTransformerFactory saxTFactory =
((javax.xml.transform.SAXTransformerFactory) tFactory);
// Create a Templates ContentHandler to handle parsing of the
// stylesheet.
javax.xml.transform.sax.TemplatesHandler templatesHandler =
saxTFactory.newTemplatesHandler();
// Create an XMLReader and set its ContentHandler.
org.xml.sax.XMLReader reader =
org.xml.sax.helpers.XMLReaderFactory.createXMLReader();
reader.setContentHandler(templatesHandler);
// Parse the stylesheet.
reader.parse("foo.xsl");
// Get the Templates object (generated during the parsing of the stylesheet)
// from the TemplatesHandler.
javax.xml.transform.Templates templates =
templatesHandler.getTemplates();
// Create a Transformer ContentHandler to handle parsing of
// the XML Source.
javax.xml.transform.sax.TransformerHandler transformerHandler
= saxTFactory.newTransformerHandler(templates);
// Reset the XMLReader's ContentHandler to the TransformerHandler.
reader.setContentHandler(transformerHandler);
// Set the ContentHandler to also function as a LexicalHandler, which
// can process "lexical" events (such as comments and CDATA).
reader.setProperty("http://xml.org/sax/properties/lexical-handler",
transformerHandler);
// Set up a Serializer to serialize the Result to a file.
org.apache.xalan.serialize.Serializer serializer =
org.apache.xalan.serialize.SerializerFactory.getSerializer
(org.apache.xalan.templates.OutputProperties.getDefaultMethodProperties
("xml"));
serializer.setOutputStream(new java.io.FileOutputStream("foo.out"));
// The Serializer functions as a SAX ContentHandler.
javax.xml.transform.Result result =
new javax.xml.transform.sax.SAXResult(serializer.asContentHandler());
transformerHandler.setResult(result);
// Parse the XML input document.
reader.parse("foo.xml");
|
 |
 |
 |
 |
 |
If you want to perform
multiple transformations with the same Templates object and a
TransformerHandler, you must create a new TransformerHandler for
each transformation. The Xalan-Java implementation of
TransformerHandler (
TransformerHandlerImpl fails to respond to events after the
first endDocument event occurs. |
|
 |
 |
 |
 |
Working with XPath
expressions |
 |
 |
 |
 |
|
|
XSLT
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.
XPath is
an independent entity, with clients other than XSLT processors
(such as XPointer). Accordingly, Xalan-Java 2 has packaged XPath as
a separate module (org.apache.xpath and its subpackages), although
concurrently this module does use some utility classes packaged in
org.apache.xalan.utils. The org.apache.xpath.XPathAPI class
contains convenience methods that you can use to return single DOM
Nodes, NodeIterators, and XObjects. Apart from their own
functionality, these methods also provide a path into the
lower-level XPath API that you may find useful.
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 in an HTML client.
- Specify
the XML source document and XSL stylesheet.
You can use the DocumentURL and StyleURL PARAM tags or the
setdocumentURL() and
setStyleURL() methods. If the XML document contains a
stylesheet Processing Instruction (PI), you do not need to specify
an XSL stylesheet.
- Call the
transformToHtml() or
getHtmlText() method, which performs the transformation and
returns the new document as a String.
 |
The transformToHTML()
method takes arguments for the XML source document and XSL
stylesheet. The getHtmlText() method takes no arguments: it uses
property or parameter settings, as in the example
below. |
For an
example, see the AppletXMLtoHTML sample
applet. The <applet> tag is in
samples/AppletXMLtoHTML/client.html:
 |
 |
 |
 |
<applet
name="xslControl"
code="org.apache.xalan.client.XSLTProcessorApplet.class"
archive="../../bin/xalan.jar,../../bin/xml-apis.jar,../../bin/xercesImpl.jar"
height="0"
width"0">
<param name="documentURL" value="xalanApplets.xml"/>
<param name="styleURL" value="s1ToHTML.xsl"/>
</applet>
|
 |
 |
 |
 |
When the
user clicks the Transform button, the HTML client calls the
getHtmlText() method, and puts the returned HTML text in a frame
for the user to view.
For
samples, see AppletXMLtoHTML.
|
|
The JAXP strategy of reading system properties generates
SecurityExceptions when you attempt to run Xalan-Java applets in
the Netscape Communicator 4.7.
Stuart Connell <Stuart.Connell@compuware.com>
reports that the Xalan-Java applet wrapper does work in Netscape
Communicator 6, provided that you avoid calls to the AppletContext
showStatus() method. In other words, you can remove the
showStatus() calls from
org.apache.xalan.client.XSLTProcessorApplet, and run Xalan-Java
applets from Netscape Communicator 6. This appears to be a Netscape
bug, which hopefully will be fixed soon. For more information, see
Bugzilla
bug 3231.
|
|
 |
 |
 |
 |
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 web browsers. To respond to HTTP GET requests, all you need
to do is overwrite the HttpServlet doGet() method with a procedure
that instantiates a Transformer and uses it to perform a
transformation. As the following example shows, you can generate a
ResultStream that a PrintWriter writes to the HttpResponse
OutputStream, returning the transformation output to the web
browser.
 |
 |
 |
 |
public class SampleXSLTServlet extends javax.servlet.http.HttpServlet {
public final static String FS = System.getProperty("file.separator");
// Respond to HTTP GET requests from browsers.
public void doGet (javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
// Set content type for HTML.
response.setContentType("text/html; charset=UTF-8");
// Output goes to the response PrintWriter.
java.io.PrintWriter out = response.getWriter());
try
{
javax.xml.transform.TransformerFactory tFactory =
javax.xml.transform.TransformerFactory.newInstance();
//get the real path for xml and xsl files.
String ctx = getServletContext().getRealPath("") + FS;
// Get the XML input document and the stylesheet, both in the servlet
// engine document directory.
javax.xml.transform.Source xmlSource =
new javax.xml.transform.stream.StreamSource
(new java.net.URL("file", "", ctx+"foo.xml").openStream());
javax.xml.transform.Source xslSource =
new javax.xml.transform.stream.StreamSource
(new java.net.URL("file", "", ctx+"foo.xsl").openStream());
// Generate the transformer.
javax.xml.transform.Transformer transformer =
tFactory.newTransformer(xslSource);
// Perform the transformation, sending the output to the response.
transformer.transform(xmlSource,
new javax.xml.transform.stream.StreamResult(out));
}
// If an Exception occurs, return the error to the client.
catch (Exception e)
{
out.write(e.getMessage());
e.printStackTrace(out);
}
// Close the PrintWriter.
out.close();
}
}
|
 |
 |
 |
 |
For a
working sample, see SimpleXSLTServlet.
In the
preceding example, the URLs for the XML document and XSL stylesheet
are hardcoded in the servlet. You can also create a servlet that
parses the request URL for input parameters specifying the XML
document, XSL stylesheet, and any relevant stylesheet parameters.
For samples, see UseStylesheetParamServlet
and XSLTServletWithParams.
For a more robust and complex sample that also employs a properties
file to determine which stylesheet to use depending on the client
browser/device, see ApplyXSLT.
|
|
|
A given
Templates object may be used repeatedly and even in multiple
threads running concurrently for the transformation of XML input,
but you should use the Templates object to instantiate a separate
Transformer for each transformation you perform. The Templates
object is an immutable runtime representation of the structure and
content of a stylesheet (which may include and import multiple
stylesheet sources). A Transformer, on the other hand, is a
lightweight object that tracks state information during the
transformation, and should only be used to perform a single
transformation.
If you
want to perform multiple transformations (sequentially or
concurrently) with the same stylesheet instructions, do the
following:
- Use the
TransformerFactory
newTemplates(Source xslSource) method to create a Templates
object.
- For each
transformation, use the Templates object
newTransformer() method to create a Transformer, and use that
Transformer's
transform(Source xmlSource, Result transformResult) method to
perform the transformation.
For an
example, see Examples.exampleUseTemplatesObj() in the trax sample.
|
|