14 Using the XSLT Processor for Java
An explanation is given of how to use the Extensible Stylesheet Language Transformation (XSLT) processor for Java.
Introduction to the XSLT Processor
Topics include prerequisites, standards and specifications, and an overview of XML transformation with XSLT.
Prerequisites for Using the XSLT Processor for Java
XSLT is a language, based on Extensible Markup Language (XML), that you can use to transform one XML document into another text document. For example, you can use XSLT to accept an XML data document as input, perform arithmetic calculations on element values in the document, and generate an Extensible HyperText Markup Language (XHTML) document that shows the calculation results.In XSLT, XPath is used to navigate and process elements in the source node tree. XPath models an XML document as a tree made up of nodes; the types of nodes in the XPath node tree correspond to the types of nodes in a DOM tree.
This chapter assumes that you are familiar with these World Wide Web Consortium (W3C) standards:
-
Extensible Stylesheet Language (XSL) and Extensible Stylesheet Language Transformations (XSLT). For a general introduction to XSLT, see the XML resources listed in Related Documents.
Standards and Specifications for the XSLT Processor for Java
The Oracle XML Developer's Kit (XDK) XSLT processor supports the XSLT2.0 recommendation.
XPath, which is the navigational language used by XSLT and other XML languages, is available in two versions: XPath 2.0 and the XPath 1.0 Recommendation.
XML Transformation with XSLT 1.0 and 2.0
Oracle XML Developer's Kit (XDK) provides several useful features not included in XSLT 1.0. To use XSLT 2.0, set the version
attribute in your stylesheet.
<? xml-stylesheet version="2.0" ... ?>
Useful XSLT 2.0 features include these:
-
User-defined functions
You can use the
<xsl:function>
declaration to define functions. This element must have onename
attribute to define the function name. The value of thename
attribute is aQName
. The content of the<xsl:function>
element is zero or morexsl:param
elements that specify the formal arguments of the function, followed by a sequence constructor that defines the value returned by the function.QName
can have a null namespace, but user-defined functions must have a non-null namespace. That is, ifabc
is defined as a namespace, thenadd
is not a legal user-defined function, butabc:add
is. -
Grouping
You can use the
<xsl:for-each-group>
element,current-group()
function, andcurrent-grouping-key()
function to group items. -
Multiple result documents
You can use the
<xsl:result-document>
element to create a result tree. The content of the<xsl:result-document>
element is a sequence constructor for the children of the document node of the tree.For example, this element enables you to accept an XML document as input and break it into separate documents. You can take an XML document that describes a list of books and generate an XHTML document for each book. You can then validate each output document.
-
Temporary trees
Instead of representing the intermediate XSL transformation results and XSL variables as strings, as in XSLT 1.0, you can store them as a set of document nodes. The document nodes, which you can construct with the
<xsl:variable>
,<xsl:param>
, and<xsl:with-param>
elements, are called temporary trees. -
Character mapping
In XSLT 1.0, you had to use the
disable-output-escaping
attribute of the<xsl:text>
and<xsl:value-of>
elements to specify character escaping. In XSLT 2.0, you can declare mapping characters with an<xsl:character-map>
element as a top-levelstylesheet
element. You can use this element to generate files with reserved or invalid XML characters in the XSLT outputs, such as<
,>
, and&
.
See Also:
XSL Transformations (XSLT) Version 2.0 for explanation and examples of XSLT 2.0 features
Using the XSLT Processor for Java: Overview
The XDK XSLT processor transforms an XML document into another text-based document, with a format such as XML, HTML, XHTML, or plain text. You can invoke the processor programmatically by using an application programming interface (API) or run it from the command line.
The XSLT processor can perform these tasks:
-
Reads one or more XSLT stylesheets. The processor can apply multiple stylesheets to a single XML input document and generate different results.
-
Reads one or more input XML documents. The processor can use a single stylesheet to transform multiple XML input documents.
-
Builds output documents by applying the rules in the stylesheet to the input XML documents. The output is a Document Object Model (DOM) tree, output stream, or series of Simple API for XML (SAX) events.
Whereas XSLT is a function-based language that generally requires a DOM of the input document and stylesheet to perform the transformation, the XDK Java implementation of the XSLT processor can use SAX to create a stylesheet object to perform transformations with higher efficiency and fewer resources. You can reuse this stylesheet object to transform multiple documents without reparsing the stylesheet.
Using the XSLT Processor for Java: Basic Process
The basic design of the XSLT processor for Java is presented.
Figure 14-1 illustrates this process.
See Also:
Oracle Database XML Java API Reference to learn about the XMLParser
and XSDBuilder
classes
Figure 14-1 Using the XSLT Processor for Java
Description of "Figure 14-1 Using the XSLT Processor for Java"
Running the XSLT Processor Demo Programs
Demo programs for the XSLT processor for Java are included in $ORACLE_HOME/xdk/demo/java/parser/xslt
.
Table 14-1 describes the XML files and programs that you can use to test the XSLT processor.
Table 14-1 XSLT Processor Sample Files
File | Description |
---|---|
|
A sample XML document that you can use to test ID selection and pattern matching. Its associated stylesheet is |
|
A sample stylesheet for use with |
|
A sample XML data document that you can use to perform simple arithmetic. Its associated stylesheet is |
|
A sample stylesheet for use with |
|
A sample XML data document that you can use to test for source tree numbering. The document describes the structure of a book. |
|
A sample stylesheet for us with |
|
A sample XML data document that you can use to test for |
|
A sample stylesheet for use with |
|
A sample XML data document that you can use with |
|
A sample stylesheet for us with |
|
A sample XML data document that you can use to test perform various string test and manipulations. Its associated stylesheet is |
|
A sample stylesheet for us with |
|
A stylesheet that provides the framework for an HTML page. The stylesheet is included by |
|
A sample XML data document that you can use to test the use of XSL variables. The document describes the structure of a book. Its associated stylesheet is |
|
A stylesheet for use with |
|
A sample application that offers a simple example of how to use the XSL processing capabilities of the Oracle XSLT processor. The program transforms an input XML document by using an input stylesheet. This program builds the result of XSL transformations as a Run this program with any XSLT stylesheet in the directory as a first argument and its associated |
|
A sample application that offers a simple example of how to use the XSL processing capabilities of the Oracle XSLT processor. The program transforms an input XML document by using an input stylesheet. This program outputs the result to a stream and supports |
Documentation for how to compile and run the sample programs is located in the README
. The basic steps are:
Using the XSLT Processor Command-Line Utility
XDK includes oraxsl
, which is a command-line Java interface that can apply a stylesheet to multiple XML documents. The $ORACLE_HOME/bin/oraxsl
and %ORACLE_HOME%\bin\oraxsl.bat
shell scripts execute the oracle.xml.jaxb.oraxsl
class.
To use oraxsl
ensure that your CLASSPATH
is set as described in Setting Up the XDK for Java Environment.
Use this syntax on the command line to invoke oraxsl
:
oraxsl options source stylesheet result
The oraxsl
utility expects a stylesheet, an XML file to transform, and an optional result file. If you do not specify a result file, then the utility sends the transformed document to standard output. If multiple XML documents must be transformed by a stylesheet, then use the -l
or -d
options with the -s
and -r
options. These and other options are described in Table 14-2.
Table 14-2 Command-Line Options for oraxsl
Option | Description |
---|---|
|
Shows warnings. By default, warnings are turned off. |
|
Specifies file into which the program writes errors and warnings. |
|
Lists files to be processed. |
|
Specifies the directory that contains the files to transform. The default behavior is to process all files in the directory. If only a subset of the files in that directory, for example, one file, must be processed, then change this behavior by setting |
|
Specifies extensions for the files to be excluded. Use this option with |
|
Specifies extensions for the files to be included. Use this option with |
|
Specifies the stylesheet. If you set |
|
Specifies the extension to use for results. If you set |
|
Specifies the directory in which to place results. You must set this option with the |
|
Lists parameters. |
|
Specifies the number of threads to use for processing. Using multiple threads can provide performance improvements when processing multiple documents. |
|
Generates verbose output. The program prints some debugging information and can help in tracing any problems that are encountered during processing. |
|
Generates debugging output. By default, debug mode is disabled. A graphical user interface (GUI) version of the XSLT debugger is available in Oracle JDeveloper. |
Using the XSLT Processor Command-Line Utility: Example
You can test oraxsl
on the various XML files and stylesheets in $ORACLE_HOME/xdk/demo/java/parser/xslt
.
Example 14-1 displays the contents of math.xml
.
The XSLT stylesheet named math.xsl
is shown in Example 14-2.
You can run the oraxsl
utility on these files to produce HTML output as shown in this example:
oraxsl math.xml math.xsl math.htm
The output file math.htm
is shown in Example 14-3.
Example 14-1 math.xml
<?xml version="1.0"?>
<doc>
<n1>5</n1>
<n2>2</n2>
<div>-5</div>
<mod>2</mod>
</doc>
Example 14-2 math.xsl
<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="doc">
<HTML>
<H1>Test for mod.</H1>
<HR/>
<P>Should say "1": <xsl:value-of select="5 mod 2"/></P>
<P>Should say "1": <xsl:value-of select="n1 mod n2"/></P>
<P>Should say "-1": <xsl:value-of select="div mod mod"/></P>
<P><xsl:value-of select="div or ((mod)) | or"/></P>
</HTML>
</xsl:template>
</xsl:stylesheet
Example 14-3 math.htm
<HTML>
<H1>Test for mod.</H1>
<HR>
<P>Should say "1": 1</P>
<P>Should say "1": 1</P>
<P>Should say "-1": -1</P>
<P>true</P>
</HTML>
Transforming XML
Topics here include performing basic XSL transformation and getting DOM results from a transformation.
Performing Basic XSL Transformation
The fundamental classes used by the XSLT processor are DOMParser
and XSLProcessor
. The XSL2Sample.java
demo program provides a good illustration of how to use these classes to transform an XML document with an XSLT stylesheet.
Classes DOMParser
and XSLProcessor
are described in Using the XSLT Processor for Java: Overview.
Use these basic steps to write Java programs that use the XSLT processor:
Related Topics
Getting DOM Results from an XSL Transformation
Sample programs show how to obtain the results from an XSL transformation.
The XSLSample.java
demo program shows how to generate an oracle.xml.parser.v2.XMLDocumentFragment
object as the result of an XSL transformation. An XMLDocumentFragment
is a lightweight Document
object that extracts a portion of an XML document tree. The XMLDocumentFragment
class implements the org.w3c.dom.DocumentFragment
interface.
The XSL2Sample.java
demo program shows how to generate a DocumentFragment
object. The basic steps for transforming XML are the same as those described in Performing Basic XSL Transformation. The only difference is in the arguments passed to the XSLProcessor.processXSL()
method. This code fragment from XSL2Sample.java
shows how to create the DOM fragment and then print it to standard output:
XMLDocumentFragment result = processor.processXSL(xsl, xml); result.print(System.out);
Table 14-4 lists some XMLDocumentFragment
methods you can use to manipulate the object.
Table 14-4 XMLDocumentFragment Methods
Method | Description |
---|---|
|
Gets a |
|
Gets the local name for this element |
|
Gets the namespace URI of this element |
|
Gets the node immediately following the current node |
|
Gets the name of the node |
|
Gets a code that represents the type of the underlying object |
|
Gets the parent of the current node |
|
Gets the node immediately preceding the current node |
|
Reports SAX events from a DOM tree |
Programming with Oracle XSLT Extensions
Topics here include an overview, specifying namespaces for extension functions, using Java methods, using constructor extension functions, and using return value extension functions.
Overview of Oracle XSLT Extensions
The XSLT 1.0 standard defines two kinds of extensions: extension elements and extension functions. XDK provides extension functions for XSLT processing that enable users of the XSLT processor to invoke any Java method from XSL expressions. When using Oracle XSLT extensions, follow these guidelines:
-
When you define an XSLT extension in a given programming language, you can use only the XSLT stylesheet with XSLT processors that can invoke this extension. Thus, only the Java version of the processor can invoke extension functions that are defined in Java.
-
Use XSLT extensions only if the built-in XSL functions cannot solve a given problem.
-
As explained in this section, the namespace of the extension class must start with the proper URL.
These Oracle extension functions are especially useful:
-
<ora:output>
, you can use<ora:output>
as a top-level element or in an XSL template. If used as a top-level element, it is similar to the<xsl:output>
extension function, except that it has an additionalname
attribute. When used as a template, it has the additional attributesuse
andhref
. This function is useful for creating multiple outputs from one XSL transformation. -
<ora:node-set>
, which converts a result tree fragment into a node-set. This function is useful when you want to refer the existing text or intermediate text results in XSL for further transformation.
Specifying Namespaces for XSLT Extension Functions
The Oracle Java extension functions belong to the namespace that corresponds to this Universal Resource Identifier (URI): http://www.oracle.com/XSL/Transform/java/
. An extension function that belongs to this namespace refers to methods in the Java classname
, so that you can construct URIs in this format: http://www.oracle.com/XSL/Transform/java/classname
.
For example, you can use this namespace to invoke java.lang.String
methods from XSL expressions: http://www.oracle.com/XSL/Transform/java/java.lang.String
.
Note:
When assigning the xsl
prefix to a namespace, the correct URI is xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
. Any other URI fails to give correct output.
Using Static and Nonstatic Java Methods in XSLT
If a Java method is a nonstatic method of a class then the first parameter is used as the instance on which the method is invoked, and the rest of the parameters are passed to the method. If the extension function is a static method, however, then all the parameters of the extension function are passed as parameters to the static function.
Example 14-4 shows how to use the java.lang.Math.ceil()
method in an XSLT stylesheet.
For example, you can create Example 14-4 as stylesheet ceil.xsl
and then apply it to any well-formed XML document. For example, run the oraxsl
utility:
oraxsl ceil.xsl ceil.xsl ceil.out
The output document ceil.out
has this content:
<?xml version = '1.0' encoding = 'UTF-8'?> 13
Note:
The XSL class loader recognizes only statically added JARs and paths in the CLASSPATH
and those specified by wrapper.classpath
. Files added dynamically are not visible to XSLT processor.
Example 14-4 Using a Static Function in an XSLT Stylesheet
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://www.oracle.com/XSL/Transform/java/java.lang.Math"> <xsl:template match="/"> <xsl:value-of select="math:ceil('12.34')"/> </xsl:template> </xsl:stylesheet>
Using Constructor Extension Functions
The extension function new
creates a new instance of a class and acts as the constructor.
Example 14-5 creates a new String
object with the value Hello World
, stores it in the XSL variable str1
, and then outputs it in uppercase.
For example, you can create this stylesheet as hello.xsl
and apply it to any well-formed XML document. For example, run the oraxsl
utility:
oraxsl hello.xsl hello.xsl hello.out
The output document hello.out
has this content:
<?xml version = '1.0' encoding = 'UTF-8'?> HELLO WORLD
Example 14-5 Using a Constructor in an XSLT Stylesheet
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:jstring="http://www.oracle.com/XSL/Transform/java/java.lang.String"> <xsl:template match="/"> <!-- creates a new java.lang.String and stores it in the variable str1 --> <xsl:variable name="str1" select="jstring:new('HeLlO wOrLd')"/> <xsl:value-of select="jstring:toUpperCase($str1)"/> </xsl:template> </xsl:stylesheet>
Using Return Value Extension Functions
The result of an extension function can be of any type, including the five types defined in XSL and the additional simple XML Schema data types defined in XSLT 2.0:
-
NodeSet
-
Boolean
-
String
-
Number
-
ResultTree
You can store these data types in variables or pass them to other extension functions. If the result is one of the five types defined in XSL, it can be returned as the result of an XSL expression.
The XSLT Processor supports overloading based on the number of parameters and type. The processor performs implicit type conversion between the five XSL types as defined in XSL. It performs type conversion implicitly among these data types, and also from NodeSet
to these data types:
-
String
-
Number
-
Boolean
-
ResultTree
Overloading based on two types that can be implicitly converted to each other is not permitted. This overloading causes an error in XSL because String
and Number
can be implicitly converted to each other:
-
overloadme(int i){}
-
overloadme(String s){}
Mapping between XSL data types and Java data types is done as follows:
String -> java.lang.String Number -> int, float, double Boolean -> boolean NodeSet -> NodeList ResultTree -> XMLDocumentFragment
The stylesheet in Example 14-6 parses the variable.xml
document, which is located in the directory $ORACLE_HOME/xdk/demo/java/parser/xslt
, and retrieves the value of the <title>
child of the <chapter>
element.
You can create Example 14-6 as gettitle.xsl
and then run oraxsl
:
oraxsl gettitle.xsl gettitle.xsl variable.out
The output document variable.out
has this content:
<?xml version = '1.0' encoding = 'UTF-8'?> The value of the title element is: Section Tests
Example 14-6 gettitle.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:parser = "http://www.oracle.com/XSL/Transform/java/oracle.xml.parser.v2.DOMParser" xmlns:document = "http://www.oracle.com/XSL/Transform/java/oracle.xml.parser.v2.XMLDocument"> <xsl:template match ="/"> <!-- Create a new instance of the parser and store it in myparser variable --> <xsl:variable name="myparser" select="parser:new()"/> <!-- Call an instance method of DOMParser. The first parameter is the object. The PI is equivalent to $myparser.parse('file:/my_path/variable.xml'). Note that you should replace my_path with the absolute path on your system. --> <xsl:value-of select="parser:parse($myparser, 'file:/my_path/variable.xml')"/> <!-- Get the document node of the XML Dom tree --> <xsl:variable name="mydocument" select="parser:getDocument($myparser)"/> <!-- Invoke getelementsbytagname on mydocument --> <xsl:for-each select="document:getElementsByTagName($mydocument,'chapter')"> The value of the title element is: <xsl:value-of select="docinfo/title" /> </xsl:for-each> </xsl:template> </xsl:stylesheet>
Tips and Techniques for Transforming XML
Topics here include using XSLT to merge XML documents and creating an HTML input form based on the columns of a database table.
Merging XML Documents with XSLT
Examples show how to merge XML documents using XSLT.
Merging Documents with appendChild() discusses the DOM technique for merging documents. If the merging operation is simple, then you can also use an XSLT-based approach. For example, you might want to merge the XML documents shown in Example 14-7 and Example 14-8.
Example 14-9 displays a sample stylesheet that merges the two XML documents based on matching the <key/>
element values.
Create the XML files in Example 14-7, Example 14-8, and Example 14-9 and run this at the command line:
oraxsl msg_w_num.xml msgmerge.xsl msgmerge.xml
Example 14-10 shows the output document, which merges the data contained in msg_w_num.xml
and msg_w_text.xml
.
This technique is not as efficient for larger files as an equivalent database join of two tables, but it is useful if you have only XML files.
Example 14-7 msg_w_num.xml
<messages> <msg> <key>AAA</key> <num>01001</num> </msg> <msg> <key>BBB</key> <num>01011</num> </msg> </messages>
Example 14-8 msg_w_text.xml
<messages> <msg> <key>AAA</key> <text>This is a Message</text> </msg> <msg> <key>BBB</key> <text>This is another Message</text> </msg> </messages>
Example 14-9 msgmerge.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <!-- store msg_w_text.xml in doc2 variable --> <xsl:variable name="doc2" select="document('msg_w_text.xml')"/> <!-- match each node in input xml document, that is, msg_w_num.xml --> <xsl:template match="@*|node()"> <!-- copy the current node to the result tree --> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- match each <msg> element in msg_w_num.xml --> <xsl:template match="msg"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> <!-- insert two spaces so indentation is correct in output document --> <xsl:text> </xsl:text> <!-- copy <text> node from msg_w_text.xml into result tree --> <text><xsl:value-of select="$doc2/messages/msg[key=current()/key]/text"/> </text> </xsl:copy> </xsl:template> </xsl:stylesheet>
Example 14-10 msgmerge.xml
<?xml version = '1.0' encoding = 'UTF-8'?> <messages> <msg> <key>AAA</key> <num>01001</num> <text>This is a Message</text> </msg> <msg> <key>BBB</key> <num>01011</num> <text>This is another Message</text> </msg> </messages>
Creating an HTML Input Form Based on the Columns in a Table
To generate an HTML form for inputting data that uses column names from a database table, you can use the XML SQL Utility (XSU) to get an XML document based on the user_tab_columns
table and then use XSLT to transform the XML into an HTML form.