© Copyright IBM Corporation 2004Course materials may not be reproduced in whole or in part without the prior written permission of IBM.
Welcome to:
3.1
Java Programming with XSLTJava Programming with XSLT
© Copyright IBM Corporation 2004
After completing this unit, you should be able to:Understand how to call the XSLT processor from Java
Explain how to feed documents to the XSL processorDescribe tool optionsDescribe performance considerations
Unit Objectives
© Copyright IBM Corporation 2004
XSL Transformations (XSLT) OverviewAn XSL Transformation accepts XML from the source abstract tree model of document, known as the Source Tree. . .. . .and processes this to produce a Result Tree.
The XSL stylesheet defines the rules for transformation, based on the XML elements and attributes in the source tree. The stylesheet also may contain formatting information called format objects (or FOs) and applies those objects against the transformation.
FOP is an acronym for formatting object processor
A single stylesheet can apply to multiple XML documents, provided the elements and structure are consistent with those specified by the style sheet.Note that XSL does not require result trees to use XSL-FO and thus can be used for general XML transformations. For example, XSL can be used to transform XML into well-formed HTML, that is, XML that uses the element types and attributes defined by HTML.
© Copyright IBM Corporation 2004
XSL Transformations (XSLT) Overview
XML Document
output (Result Tree)
Source Tree
XML application
XSL Stylesheet Processor
formattingtransformation
Transform Result Tree (optional)
(1)
(2)
(3)
(4) XSL Stylesheet
(5)
© Copyright IBM Corporation 2004
XSL Transformations (XSLT) Overview Before we move on to an example, note also that the source XML document (1) can invoke multiple XSL stylesheets (4). For example, the XML source could be processed by XSL (3) to render HTML, an altered form of XML, voice markup, or rendered for print ... (5) all from the same source document invoking multiple stylesheets.These transforms (3) could occur
As separate parallel processes (each invocation running an XSL processor in a separate memory space); Or sequentially (each invocation running after the previous one completes). The advantage to parallel processing is that an XSLT error in one stylesheet will not prevent the others from running, whereas in sequential processing, any downstream process will be terminated as well. The disadvantage of parallel processing is one of system memory usage.
© Copyright IBM Corporation 2004
XSLT Example (1 of 3)The next five charts can be better understood in light of an executable example demonstrated using Studio.
The source code for this file can be found in Package Explorer:Project: XML ProgrammingFolder: dataFiles: BooksXSLT.xml and BooksXSLT.xsl
To execute in Studio 5.1:Open BooksXSLT.xsl with the XSL EditorThis should produce a picture that looks like the next pageThe important point is should give you access to this:
Transform
© Copyright IBM Corporation 2004
XSLT Example (2 of 3) Transform
to create this
uncomment and try again
© Copyright IBM Corporation 2004
XSLT Example (3 of 3)<list> <book ID="123"> <chapter>First Chapter</chapter> <chapter>Second Chapter</chapter> <appendix>XSLT reference</appendix> </book></list>
<xsl:stylesheet xmlns:xsl='... <xsl:template match="//book"> <xsl:for-each select="*"> <P /> <xsl:choose> <xsl:when test='name()="chapter"'>Chapter: </xsl:when> <xsl:when test='name()="appendix"'>Appendix: </xsl:when> <xsl:otherwise>Index: </xsl:otherwise> </xsl:choose> <xsl:value-of select="." /> </xsl:for-each> </xsl:template></xsl:stylesheet>
<P/>Chapter: First Chapter<P/>Chapter: Second Chapter<P/>Appendix: XSLT reference
Books.html
Books.xsl
Books.xml
© Copyright IBM Corporation 2004
How Do XSLT and Java Fit Together?Java-based XML parsers make the data accessible.XSL Transformations allow you to actually do something with the data.
Java-based XSLT processors provide a framework to transform the data into several formats:
HTMLXMLWMLOthers
Apache Xalan provides the proper reference implementations for XSL transformations in Java.
© Copyright IBM Corporation 2004
What Can Be the Input and Output?XML Input types (Source)
FilesStreamsDOM objectsSAX Event StreamMixed and/or multiple sources
Output types (Result)StringsStreamsFilesSAX EventsPipelines
© Copyright IBM Corporation 2004
TrAX and JAXPTrAX - Transformation API for XML
Included since JAXP 1.1 Includes APIs for XSLT TransformationPackage javax.xml.transform.∗
JAXP provides an abstraction layer for:DOM and SAX parsersXSLT processors
JAXP defines the interface, not the implementation.Provides a common interface for creating and using the standard SAX, DOM, and XSLT APIs in Java, regardless of which implementation is actually being used.Apache's Xalan provides a reference implementation of JAXP and TrAX.
© Copyright IBM Corporation 2004
TrAX ModelTransformerFactory
Processes transformation instructionsProduces Templates
Contains processed transformation instructionsProvides a transformer
Or simple TransformersTransforms sources into a resultProcess source based on template instructions or directly from the transformation source (file.xsl)
To use the TrAX interface:1. Create a TransformerFactory2. Generate a transformer from templates or factory3. Transformer accepts sources and produces a result
© Copyright IBM Corporation 2004
TrAX Patterns (1 of 2)Processor
Generic concept for the set of objects that implement the TrAX interfacesRepresents the stylesheet engine
TransformerFactoryVendor-neutral Processor interface for XSLTDirect factory for transformer objectsFactory for templates objectsManage processor specific features
TemplatesRun-time representation of transformation instructionsOptimized in memory and thread safeRepresents the actual stylesheet
© Copyright IBM Corporation 2004
TrAX Patterns (2 of 2)Transformer
Performs the transformationAssociated with a single stylesheet
SourceSingle vendor-neutral object for multiple types of inputDefined types for streams, DOM and SAXRepresents any input type
ResultSingle object for multiple types of outputDesigned for simple process method signaturesDefined types for streams, DOM and SAX
© Copyright IBM Corporation 2004
The program is available in Studio as BasicTransform.javaThis program requires two inputs:
An XSL source, data/booklist.xsl The XML instance is again data/books.xml
The Arguments tab is shown at the left (a space is the argument separator); the output is at the right.
Sample Program for Basic Transformation
© Copyright IBM Corporation 2004
Basic Transformation Steps
TransformerFactory tFactory = TransformerFactory.newInstance();
Use the TransformerFactory to process the stylesheet source and generate a transformer.Transformer transformer = tFactory.newTransformer( xslSource );
Use the transformer to transform the XML source and send the results to the result output stream.
transformer.transform( xmlSource, result );
Create source and result objects for the XSL and XML sources, and the output.
Source is a javax.xml.transform.source.StreamSourceResult is a javax.xml.transform.source.StreamResult
Source xslSource = new StreamSource( args[0] );Source xmlSource = new StreamSource( args[1] );Result result = new StreamResult(System.out);
Instantiate a TransformerFactory.
© Copyright IBM Corporation 2004
The program is available in Studio as SAXTransform.javaThis program requires two inputs:
An XSL source, data/booklist.xsl An XML instance, data/books.xml
The Arguments tab is shown at the left (a space is the argument separator); the output is at the right.
Sample Program for SAX Transformations
© Copyright IBM Corporation 2004
SAX Transformations (1 of 2)
Process the stylesheet and convert to templates.
Instantiate TransformerFactory, test to ensure it knows SAX, and cast it to a SAXTransformerFactory.
// Create content handler to parse XSL source (it's normal xml)TemplatesHandler xslHandler = saxTFactory.newTemplatesHandler();XMLReader reader = XMLReaderFactory.createXMLReader();reader.setContentHandler( xslHandler );reader.parse( args[0] );// Obtain a Templates object based on parsed XSLTemplates templates = xslHandler.getTemplates();
TransformerFactory tFactory = TransformerFactory.newInstance();// Does this TransformerFactory support both SAX Source & Resultif ( !( tFactory.getFeature( SAXSource.FEATURE ) && tFactory.getFeature( SAXResult.FEATURE )) ) throw new Exception( "The TransformerFactory does not support SAX input and SAX output");// Cast the normal Factory into a SAXTransformerFactorySAXTransformerFactory saxTFactory = ((SAXTransformerFactory) tFactory);
© Copyright IBM Corporation 2004
SAX Transformations (2 of 2)
Parse the XML document.Source events are handled by the templates handler.Resulting events are passed to the results handler.
Create a result handler based on a serializer.
Define the Templates as an Event Handler.// Create special handler to transform source XML. Set as// content handler, and lexical handler (Comments, CDATA, etc.)TransformerHandler xmlHandler = saxTFactory.newTransformerHandler( templates );reader.setContentHandler( xmlHandler );reader.setProperty( "http://xml.org/sax/properties/lexical-handler", xmlHandler);
// Serializer will output resultsSerializer serializer = SerializerFactory.getSerializer( OutputProperties.getDefaultMethodProperties( "xml" ) );serializer.setOutputStream( System.out ); // Could be any Stream// Convert Serializer into a content handlerResult result = new SAXResult( serializer.asContentHandler() );xmlHandler.setResult( result );
reader.parse( args[1] );
© Copyright IBM Corporation 2004
The program is available in Studio as DOMTransform.javaThis program requires two inputs:
An XSL source, data/booklist.xsl An XML instance, data/books.xml
The Arguments tab is shown at the left (a space is the argument separator); the output is at the right.
Sample Program for DOM Transformations
© Copyright IBM Corporation 2004
DOM Transformations (1 of 3)Generate standard DOM factory and builder, and parse the XSL template file.
Set NameSpaceAware in order to handle XSL files.
Instantiate TransformerFactory, test to ensure it supports DOM source and result types.
TransformerFactory tFactory = TransformerFactory.newInstance();// Does this TransformerFactory support both SAX Source & Resultif ( !( tFactory.getFeature( DOMSource.FEATURE ) && tFactory.getFeature( DOMResult.FEATURE )) ) throw new Exception( "The TransformerFactory does not support DOM input and DOM output");
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();// Set NamespaceAware, required when parsing XSL filesdFactory.setNamespaceAware( true );DocumentBuilder dBuilder = dFactory.newDocumentBuilder();
© Copyright IBM Corporation 2004
DOM Transformations (2 of 3)Parse XSL, create source from it, set system ID, and generate transformer from source.
Parse XML, create source from it, and set system ID.
Create an empty result to hold output.
Document xslDoc = dBuilder.parse( "booklist.xsl" );// Use the DOM Document to define a DOMSource object.DOMSource xslDomSource = new DOMSource( xslDoc );// Set the systemId, so embedded relative URLs can be locatedxslDomSource.setSystemId( "booklist.xsl" );// Process the stylesheet DOMSource and generate a TransformerTransformer transformer = tFactory.newTransformer(xslDomSource);
//Use the DocumentBuilder to parse the XML input.Document xmlDoc = dBuilder.parse( "books.xml" );// Use the DOM Document to define a DOMSource object.DOMSource xmlDomSource = new DOMSource( xmlDoc );xmlDomSource.setSystemId( "books.xml" );
// Create an empty DOMResult for the Result.DOMResult domResult = new DOMResult();// Perform transformation, placing the output in the DOMResult.transformer.transform( xmlDomSource, domResult );
© Copyright IBM Corporation 2004
DOM Transformations (3 of 3)
At this point the resulting DOM tree is sitting in the DOM result.Get the top-level node using DOMResult.getNode().
Many options are then available:Serialize the node to some output.Pass the node into another transformer.Traverse or manipulate the DOM node.
We'll serialize the output in this sample using Serializers.asDOMSerializer() as shown.
// Get Node from DOMResultsNode outputNode = domResult.getNode();// Serializer will output results to STDOUTSerializer serializer = SerializerFactory.getSerializer( OutputProperties.getDefaultMethodProperties( "xml" ) );serializer.setOutputStream( System.out ); // Or any Stream// Convert Serializer into a content handlerserializer.asDOMSerializer().serialize( outputNode );
© Copyright IBM Corporation 2004
The program is available in Studio as TrAXSerializer.javaThis program requires one input:
An XML instance, data/books.xmlThe Arguments tab is shown at the left; the output is at the right.
Sample Program for TrAX Serialization
© Copyright IBM Corporation 2004
TrAX SerializationAllows custom alteration to the <xsl:output ... > statement.
Overrides stylesheet settings.Settings are documented at: www.w3.org/TR/xslt#output.DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder docBuilder = dbf.newDocumentBuilder();Document outDoc = docBuilder.newDocument();Node doc = docBuilder.parse( new InputSource( "books.xml" ) );TransformerFactory tfactory = TransformerFactory.newInstance();// Create a basic serializer from the factoryTransformer serializer = tfactory.newTransformer();Properties oprops = new Properties();oprops.put("method", "xml"); // Define output methodoprops.put("standalone", "yes"); // Add XML decl stmt// List of elements to be enclosed within CDATA sectionsoprops.put("cdata-section-elements", "title");serializer.setOutputProperties( oprops );serializer.transform( new DOMSource( doc ), new StreamResult( System.out ) );
© Copyright IBM Corporation 2004
Dealing with Transformation Errors
Errors encountered during transformations can be handled with the ErrorListener interface.
Very similar to the SAX ErrorHandler Interface.Register using TransformerFactory.setErrorListener().
Defines three error handling methods.
Error DescriptionWarning Problems that are not errors as defined by the
XML specification. Transformation continues.Error Recoverable errors as defined by XML
specification. Transformation continues.Fatal Error Non-recoverable errors as defined by XML
specification. Application should assume XML (or XSL) is unusable (that is, well-formedness error). Parser/Transformation may abort.
© Copyright IBM Corporation 2004
Chaining Using XMLFilters
Input Source
Result
XMLFilter 1 chaining ...
XMLFilter 2 chaining ...
XMLFilter 3 chaining ...
3. Each filter requests its parent to filter first (for example, 3>2>1).
2. The last filter in the chain starts parsing process.
Chaining allows for multiple transformations to occur in a single pass.
XMLFilters are linked together to provide a pipeline.
1. Each filter defines its parent filter.
© Copyright IBM Corporation 2004
The program is available in Studio as Chaining.javaThis program requires four inputs:
Three XSL sources, data/foo1.xsl data/foo2.xsl data/foo3.xsl And an XML instance, data/books.xml
The Arguments tab is shown at below (a space is the argument separator); the output is shown in the bottom screen capture.
Sample Program for Chaining
<?xml version="1.0" encoding="UTF-8" standalone="no"?><out><some-text>default param value,text from my-var in inc2.xslMyBar</some-text></out>
© Copyright IBM Corporation 2004
Example: Chaining Using XMLFilters
// Instantiate and cast TransformerFactory.TransformerFactory tFactory = TransformerFactory.newInstance();// Dropped test to check for SAX Source/Result handlingSAXTransformerFactory saxTFactory = ( (SAXTransformerFactory) tFactory );// Create an XMLFilter for each stylesheet.Source src1 = new StreamSource( "foo1.xsl" );Source src2 = new StreamSource( "foo2.xsl" );Source src3 = new StreamSource( "foo3.xsl" );XMLFilter filter1 = saxTFactory.newXMLFilter( src1 );XMLFilter filter2 = saxTFactory.newXMLFilter( src2 );XMLFilter filter3 = saxTFactory.newXMLFilter( src3 );// Create a regular Reader object to act as holderXMLReader reader = XMLReaderFactory.createXMLReader();// Define relationship between the filtersfilter1.setParent( reader ); // Uses XMLReader as its readerfilter2.setParent( filter1 ); // Uses filter1 as its readerfilter3.setParent( filter2 ); // Uses filter2 as its reader// Create serializer to handle events and send to STDOUTSerializer serializer = SerializerFactory.getSerializer( OutputProperties.getDefaultMethodProperties( "xml" ) );serializer.setOutputStream( System.out );// filter3 outputs SAX events to the serializerfilter3.setContentHandler( serializer.asContentHandler() );filter3.parse( new InputSource( "foo.xml" ) );
© Copyright IBM Corporation 2004
Out of the Box: ApplyXSLT ServletA generic Servlet to perform transformations.
Bundled in the XalanServlet JarRuns under a Web Application Server.Can be invoked by:
Client browserServlet to Servlet call
Examples:http://localhost/servlethome/servlet.ApplyXSLT? URL=/data.xml&xslURL= /style.xslhttp://localhost/servlethome/servlet.ApplyXSLT/data.xml
Very simple designGet XML and XSL from request.Open SourceStreams for XML and XSL URLs.Pass Response Writer (out) as StreamResult during the transform.
© Copyright IBM Corporation 2004
XSLTC TranslatesTool to compile XSL stylesheets into lightweight Java code (collection of inner-classes).Callable from TrAX API.Originally developed by Sun Microsystems, but now donated to Apache XML Project.Refer to the Xalan documentation for more information.
.WML
.XSL stylesheets
.xml
XSLT Compiler
translates
XSLT Runtime Library ....
.xml
.html(1)
(2)
© Copyright IBM Corporation 2004
XSLTC Benefits and ConsiderationsPerformance
Translates transform XML documents 30-200% faster than other Java technology-based XSLT processors.
Smaller footprintAverage XSLT processor size is 600 KB.Translet size is about 130 KB.
Efficiency Fewer resources means higher server throughput.
Considerations:To compile translates, you must be running the JDK 1.2 or higher.You can run translates with the JDK or JRE 1.1.8 or higher.Not yet a full implementation of XSLT 1.0 recommendation.
© Copyright IBM Corporation 2004
The program is available in Studio as TransletSample.javaThis program requires two inputs:
An XML instance, data/books.xmlA stylesheet source, data/booklist.xsl
The Arguments tab is shown at the left; the output is at the right.
Sample Program for Translates
© Copyright IBM Corporation 2004
Using Translates with TrAXOverride normal transformer with special XSLTC transformer.
Located through system property.
Create a StreamSource to the XSL and pass it to the XSLTC special transformer.
Now you can perform normal transformations.
// Set the TransformerFactory system property with XSLTCProperties props = System.getProperties();props.put( "javax.xml.transform.TransformerFactory", "org.apache.xalan.xsltc.trax.TransformerFactoryImpl");System.setProperties( props );
// Instantiate the TransformerFactory, along with a SteamSource// XSL stylesheet to create a Transformer.TransformerFactory tFactory = TransformerFactory.newInstance();Source src = new StreamSource( "booklist.xsl" );Transformer transformer = tFactory.newTransformer( src );
// Perform transformation from a StreamSource to a StreamResult;transformer.transform( new StreamSource( "books.xml" ), new StreamResult( System.out ) );
© Copyright IBM Corporation 2004
Xalan ExtensionsProvides procedural language plugability into XSL transformations:
Normal XSLT: XPath Match >> ResultsExtension: Function Match >> Take Action >> Results
Supported Languages:Native Java support.Other languages supported through the Bean Scripting Framework (BSF).
Extension elementsProvides custom elements within the stylesheet.
Extension functionsProvides custom logic to be used during the transformation process.
© Copyright IBM Corporation 2004
Xalan Extensions - UsageIn the Stylesheet Declaration tag
Declare the lxslt namespaceDeclare a unique namespace for each extensionDeclare extension element prefixes (if extension elements are used)Exclude extension namespaces in output (Optional)
Set up a <lxslt:component> blockDefine prefixDeclare functions available to stylesheetDeclare elements available to stylesheet
Set up the <lxslt:script> element inside componentDefine the language
For Java: lang="javaclass" src="pkg.class"For Others: lang="javascript"(with the actual content inside the element)
© Copyright IBM Corporation 2004
The program is available in Studio as ExtensionTransform.javaThis program requires two inputs:
A stylesheet source, data/OnSaleExt.xslAn XML instance, data/books.xml
The Arguments tab is shown at the left; the output is at the right.
Sample Program Xalan Extension
© Copyright IBM Corporation 2004
Xalan Extension - Sample Stylesheet
Stylesheet headers
Component Block and Script element
Extension element and Extension Function
<?xml version="1.0"?><!--Sample Xalan Extention--><xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:lxslt="http://xml.apache.org/xslt"xmlns:sale="mySalePrice"extension-element-prefixes="sale">
<!-- Component block including script element for java --> <lxslt:component prefix="sale" elements="init" functions="getSalePrice getDiscountPct"> <lxslt:script lang="javaclass" src="xalan://CalcSalePrice" /> </lxslt:component> <xsl:template match="books"> <sale:init discountPct="20"/> <booklist> <xsl:apply-templates/> </booklist> </xsl:template> <xsl:template match="book"> Title: <xsl:value-of select="title"/> Author: <xsl:value-of select="author"/> Price: <xsl:value-of select="price"/> Sale : <xsl:value-of select="sale:getSalePrice(price/text())"/> </xsl:template></xsl:stylesheet>
data/OnSaleExt.xsl
© Copyright IBM Corporation 2004
Xalan Extension - Sample Class
public class CalcSalePrice {private double discountPct = 100;
// Configure Extension Element using an init methodpublic void init(
org.apache.xalan.extensions.XSLProcessorContext context,org.apache.xalan.templates.ElemExtensionCall extElem) {String discount = extElem.getAttribute("discountPct");discountPct = Double.parseDouble( discount );
} // Return sale price based on original minus discount %
public String getSalePrice( String price ) {NumberFormat nf = NumberFormat.getInstance();nf.setMaximumFractionDigits(2);nf.setMinimumFractionDigits(2);
// hack to drop "$" on double conversiondouble prc = Double.parseDouble( price.substring(1) );prc = prc - (prc * (discountPct/100) );return "$" + nf.format(prc);
} public String getDiscountPct() { return discountPct + "%"; }}
© Copyright IBM Corporation 2004
Checkpoint Questions (1 of 2)1. Which of the following statements are true? (Select all that apply)
A. JAXP and TrAX are APIsB. Xalan and JAXP are APIsC. Xalan and TrAX are implementations of the JAXP APID. Xalan is the implementation of the JAXP and TrAX APIsE. TrAX is the implementation of the JAXP API
2. Which of the following is not part of Xalan Extensions?A. Extension Functions and ElementsB. lxslt component and script tagsC. Stylesheet CompilerD. Stylesheet Headers
© Copyright IBM Corporation 2004
Checkpoint Questions (2 of 2)3. Which of the following are valid XSLT sources?
(Select all that apply)A. DOMSourceB. XSLSourceC. SAXSourceD. StreamSourceE. XMLSource
4. Which of the following XSLTC statements is false?A. Allows procedural language plugability to XSL.B. Compiles stylesheets to translet classes.C. Provides enhanced transformation performance.D. Allows Web browsers to easily transform documents.E. Requires special transformer class in TrAX.
© Copyright IBM Corporation 2004
Having completed this unit, you should be able to:Describe how to call the XSLT processor from JavaExplain how to feed documents to the XSL processorUnderstand XSLT tool optionsDescribe XSLT performance considerations
Unit Summary
Top Related