6 Using the XSLT Processor for Java

This chapter contains these topics:

Introduction to the XSLT Processor

This section contains the following topics:

Prerequisites

XSLT is an XML-based language 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 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 the following W3C standards:

Standards and Specifications

XSLT is currently available in two versions: a working draft for XSLT 2.0 and the XSLT 1.0 Recommendation. You can find the specifications at the following URLs:

XPath, which is the navigational language used by XSLT and other XML languages, is available in two versions: a working draft for XPath 2.0 and the XPath 1.0 Recommendation. You can find the specifications for the two XPath versions at the following URLs:

Oracle XDK XSLT processor implements both the XSLT and XPath 1.0 standards as well as the current working drafts of the XSLT and XPath 2.0 standards. The XDK XSLT processor supports the XPath 2.0 functions and operators. You can find the specification at the following URL:

http://www.w3.org/TR/xpath-functions/

See Also:

Chapter 31, "XDK Standards" for a summary of the standards supported by the XDK

XML Transformation with XSLT 1.0 and 2.0

In Oracle Database 10g, the XDK provides several useful features not included in XSLT 1.0. To use XSLT 2.0, set the version attribute in your stylesheet as follows:

<? xml-stylesheet version="2.0" ... ?>

Some of the most useful XSLT 2.0 features are the following:

  • User-defined functions

    You can use the <xsl:function> declaration to define functions. This element must have one name attribute to define the function name. The value of the name attribute is a QName. The content of the <xsl:function> element is zero or more xsl:param elements that specify the formal arguments of the function, followed by a sequence constructor that defines the value returned by the function.

    Note that QName can have a null namespace, but user-defined functions must have a non-null namespace. That is, if abc is defined as a namespace, then add is not a legal user-defined function, but abc:add is.

  • Grouping

    You can use the <xsl:for-each-group> element, current-group() function, and current-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 level stylesheet element. You can use this element to generate files with reserved or invalid XML characters in the XSLT outputs, such as <, >, and &.

See Also:

http://www.w3.org/TR/xslt20 for explanation and examples of XSLT 2.0 features

Using the XSLT Processor for Java: Overview

The Oracle XDK XSLT processor is a software program that transforms an XML document into another text-based format. For example, the processor can transform XML into XML, HTML, XHTML, or text. You can invoke the processor programmatically by using the APIs or run it from the command line. The XSLT processor can perform the following 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 DOM tree, output stream, or series of 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 Java XDK 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: Basic Process

Figure 6-1 depicts the basic design of the XSLT processor for Java.

See Also:

Oracle Database XML Java API Reference to learn about the XMLParser and XSDBuilder classes

Figure 6-1 Using the XSLT Processor for Java

Description of Figure 6-1 follows
Description of "Figure 6-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 6-1 describes the XML files and programs that you can use to test the XSLT processor.

Table 6-1 XSLT Processor Sample Files

File Description

match.xml

A sample XML document that you can use to test ID selection and pattern matching. Its associated stylesheet is match.xsl.

match.xsl

A sample stylesheet for use with match.xml. You can use it to test simple identity transformations.

math.xml

A sample XML data document that you can use to perform simple arithmetic. Its associated stylesheet is math.xsl.

math.xsl

A sample stylesheet for use with math.xml. The stylesheet outputs an HTML page with the results of arithmetic operations performed on element values in math.xml.

number.xml

A sample XML data document that you can use to test for source tree numbering. The document describes the structure of a book.

number.xsl

A sample stylesheet for us with number.xml. The stylesheet outputs an HTML page that calculates section numbers for the sections in the book described by number.xml.

position.xml

A sample XML data document that you can use to test for position()=X in complex patterns. Its associated stylesheet is position.xsl.

position.xsl

A sample stylesheet for use with position.xml. The stylesheet outputs an HTML page with the results of complex pattern matching.

reverse.xml

A sample XML data document that you can use with reverse.xsl to traverse backward through a tree.

reverse.xsl

A sample stylesheet for us with reverse.xml. The stylesheet output the item numbers in reverse.xml in reverse order.

string.xml

A sample XML data document that you can use to test perform various string test and manipulations. Its associated stylesheet is string.xsl.

string.xsl

A sample stylesheet for us with string.xml. The stylesheet outputs an XML document that displays the results of the string manipulations.

style.txt

A stylesheet that provides the framework for an HTML page. The stylesheet is included by number.xsl.

variable.xml

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

variable.xsl

A stylesheet for use with variable.xml. The stylesheet makes extensive use of XSL variables.

XSLSample.java

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 DocumentFragment and does not show xsl:output features.

Run this program with any XSLT stylesheet in the directory as a first argument and its associated *.xml XML document as a second argument. For example, run the program with variable.xsl and variable.xml or string.xsl and string.xml.

XSLSample2.java

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 xsl:output features. Like XSLSample.java, you can run it against any pair of XML data documents and stylesheets in the directory.


Documentation for how to compile and run the sample programs is located in the README. The basic steps are as follows:

  1. Change into the $ORACLE_HOME/xdk/demo/java/parser/xslt directory (UNIX) or %ORACLE_HOME%\xdk\demo\java\parser\xslt directory (Windows).

  2. Make sure that your environment variables are set as described in "Setting Up the Java XDK Environment".

  3. Run make (UNIX) or Make.bat (Windows) at the command line. The make file compiles the source code and then runs the XSLSample and XSLSample2 programs for each *.xml file and its associated *.xsl stylesheet. The program writes its output for each transformation to *.out.

  4. You can view the *.out files to see the output for the XML transformations. You can also run the programs on the command line as follows, where name is replaced by match, math, and so forth:

    java XSLSample name.xsl name.xml
    java XSLSample2 name.xsl name.xml
    

    For example, run the match.xml demos as follows:

    java XSLSample match.xsl match.xml
    java XSLSample2 match.xsl match.xml
    

Using the XSLT Processor Command-Line Utility

The 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 Java XDK Environment".

Use the following 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 need to be transformed by a stylesheet, then use the -l or -d options in conjunction with the -s and -r options. These and other options are described in Table 6-2.

Table 6-2 Command Line Options for oraxsl

Option Description

-w

Shows warnings. By default, warnings are turned off.

-e error_log

Specifies file into which the program writes errors and warnings.

-l xml_file_list

Lists files to be processed.

-d directory

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, need to be processed, then change this behavior by setting -l and specifying the files that need to be processed. You can also change the behavior by using the -x or -i option to select files based on their extension.

-x source_extension

Specifies extensions for the files that should be excluded. Use this option in conjunction with -d. The program does not select any files with the specified extension.

-i source_extension

Specifies extensions for the files that should be included. Use this option in conjunction with -d. The program selects only files with the specified extension.

-s stylesheet

Specifies the stylesheet. If you set -d or -l, then set -s to indicate the stylesheet to be used. You must specify the complete path.

-r result_extension

Specifies the extension to use for results. If you set -d or -l, then set -r to specify the extension to be used for the results of the transformation. So, if you specify the extension out, the program transformed an input document doc to doc.out. By default, the program places the results in the current directory. You can change this behavior by using the -o option, which allows you to specify a directory for the results.

-o result_directory

Specifies the directory in which to place results. You must set this option in conjunction with the -r option.

-p param_list

Lists parameters.

-t num_of_threads

Specifies the number of threads to use for processing. Using multiple threads can provide performance improvements when processing multiple documents.

-v

Generates verbose output. The program prints some debugging information and can help in tracing any problems that are encountered during processing.

-debug

Generates debugging output. By default, debug mode is disabled. Note that a 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 6-1 displays the contents of math.xml.

Example 6-1 math.xml

<?xml version="1.0"?>
<doc>
  <n1>5</n1>
  <n2>2</n2>
  <div>-5</div>
  <mod>2</mod>
</doc>

The XSLT stylesheet named math.xsl is shown in Example 6-2.

Example 6-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

You can run the oraxsl utility on these files to produce HTML output as shown in the following example:

oraxsl math.xml math.xsl math.htm

The output file math.htm is shown in Example 6-3.

Example 6-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

This section contains the following topics:

Performing Basic XSL Transformation

As explained in "Using the XSLT Processor for Java: Overview", 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.

Use the following basic steps to write Java programs that use the XSLT processor:

  1. Create a DOM parser object that you can use to parse the XML data documents and XSLT stylesheets. The following code fragment from XSL2Sample.java illustrates how to instantiate a parser:

    XMLDocument xml, xsldoc, out;URL xslURL;URL xmlURL;
    // ... 
    parser = new DOMParser();parser.setPreserveWhitespace(true);
    

    Note that by default, the parser does not preserve whitespace unless a DTD is used. It is important to preserve whitespace because it enables XSLT whitespace rules to determine how whitespace is handled.

  2. Parse the XSLT stylesheet with the DOMParser.parse() method. The following code fragment from XSL2Sample.java illustrates how to perform the parse:

    xslURL = DemoUtil.createURL(args[0]);
    parser.parse(xslURL);
    xsldoc = parser.getDocument();
    
  3. Parse the XML data document with the DOMParser.parse() method. The following code fragment from XSL2Sample.java illustrates how to perform the parse:

    xmlURL = DemoUtil.createURL(args[1]);
    parser.parse(xmlURL);
    xml = parser.getDocument();
    
  4. Create a new XSLT stylesheet object. You can pass objects of the following classes to the XSLProcessor.newXSLStylesheet() method:

    • java.io.Reader

    • java.io.InputStream

    • XMLDocument

    • java.net.URL

    For example, XSL2Sample.java illustrates how to create a stylesheet object from an XMLDocument object:

    XSLProcessor processor = new XSLProcessor();
    processor.setBaseURL(xslURL);
    XSLStylesheet xsl = processor.newXSLStylesheet(xsldoc);
    
  5. Set the XSLT processor to display any warnings. For example, XSL2Sample.java calls the showWarnings() and setErrorStream() methods as follows:

    processor.showWarnings(true);
    processor.setErrorStream(System.err);
    
  6. Use the XSLProcessor.processXSL() method to apply the stylesheet to the input XML data document. Table 6-3 lists some of the other available XSLProcessor methods.

    Table 6-3 XSLProcessor Methods

    Method Description

    removeParam()

    Removes parameters.

    resetParams()

    Resets all parameters.

    setParam()

    Sets parameters for the transformation.

    setBaseUrl()

    Sets a base URL for any relative references in the stylesheet.

    setEntityResolver()

    Sets an entity resolver for any relative references in the stylesheet.

    setLocale()

    Sets a locale for error reporting.


    The following code fragment from XSL2Sample.java shows how to apply the stylesheet to the XML document:

    processor.processXSL(xsl, xml, System.out);
    
  7. Process the transformed output. You can transform the results by creating an XML document object, writing to an output stream, or reporting SAX events.

    The following code fragment from XSL2Sample.java shows how to print the results:

    processor.processXSL(xsl, xml, System.out);
    

Obtaining DOM Results from an XSL Transformation

The XSLSample.java demo program illustrates 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 program illustrates 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. The following 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 6-4 lists some of the XMLDocumentFragment methods that you can use to manipulate the object.

Table 6-4 XMLDocumentFragment Methods

Method Description

getAttributes()

Gets a NamedNodeMap containing the attributes of this node (if it is an Element) or null otherwise

getLocalName()

Gets the local name for this element

getNamespaceURI()

Gets the namespace URI of this element

getNextSibling()

Gets the node immediately following the current node

getNodeName()

Gets the name of the node

getNodeType()

Gets a code that represents the type of the underlying object

getParentNode()

Gets the parent of the current node

getPreviousSibling()

Gets the node immediately preceding the current node

reportSAXEvents()

Reports SAX events from a DOM Tree


Programming with Oracle XSLT Extensions

This section contains these topics:

Overview of Oracle XSLT Extensions

The XSLT 1.0 standard defines two kinds of extensions: extension elements and extension functions. The XDK provides extension functions for XSLT processing that enable users of the XSLT processor to call any Java method from XSL expressions. Note the following guidelines when using Oracle XSLT extensions:

  • When you define an XSLT extension in a given programming language, you can only use 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 the following section, the namespace of the extension class must start with the proper URL.

The following Oracle extension functions are particularly 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 additional name attribute. When used as a template, it has the additional attributes use and href. 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 the following URI:

http://www.oracle.com/XSL/Transform/java/

An extension function that belongs to the following namespace refers to methods in the Java classname, so that you can construct URIs in the following format:

http://www.oracle.com/XSL/Transform/java/classname

For example, you can use the following namespace to call 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 Non-Static Java Methods in XSLT

If the Java method is a non-static method of the 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 6-4 shows how to use the java.lang.Math.ceil() method in an XSLT stylesheet.

Example 6-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> 

For example, you can create Example 6-4 as stylesheet ceil.xsl and then apply it to any well-formed XML document. For example, run the oraxsl utility as follows:

oraxsl ceil.xsl ceil.xsl ceil.out

The output document ceil.out has the following content:

<?xml version = '1.0' encoding = 'UTF-8'?>
13

Note:

The XSL class loader only knows about statically added JARs and paths in the CLASSPATH as well as those specified by wrapper.classpath. Files added dynamically are not visible to XSLT processor.

Using Constructor Extension Functions

The extension function new creates a new instance of the class and acts as the constructor. Example 6-5 creates a new String object with the value "Hello World," stores it in the XSL variable str1, and then outputs it in uppercase.

Example 6-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>

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 as follows:

oraxsl hello.xsl hello.xsl hello.out

The output document hello.out has the following content:

<?xml version = '1.0' encoding = 'UTF-8'?>
HELLO WORLD

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 to other extension functions. If the result is of one of the five types defined in XSL, then the result 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 the following datatypes, and also from NodeSet to the following datatypes:

  • String

  • Number

  • Boolean

  • ResultTree

Overloading based on two types that can be implicitly converted to each other is not permitted. The following overloading results in an error in XSL because String and Number can be implicitly converted to each other:

  • overloadme(int i){}

  • overloadme(String s){}

Mapping between XSL datatypes and Java datatypes is done as follows:

String     ->     java.lang.String
Number     ->     int, float, double
Boolean    ->     boolean
NodeSet    ->     NodeList
ResultTree ->     XMLDocumentFragment

The stylesheet in Example 6-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.

Example 6-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>

You can create Example 6-6 as gettitle.xsl and then run oraxsl as follows:

oraxsl gettitle.xsl gettitle.xsl variable.out

The output document variable.out has the following content:

<?xml version = '1.0' encoding = 'UTF-8'?>
The value of the title element is: Section Tests

Tips and Techniques for Transforming XML

This section lists XSL and XSLT Processor for Java hints, and contains these topics:

Merging XML Documents with 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. Suppose that you want to merge the XML documents in Example 6-7 and Example 6-8.

Example 6-7 msg_w_num.xml

<messages>
  <msg>
    <key>AAA</key>
    <num>01001</num>
  </msg>
  <msg>
    <key>BBB</key>
    <num>01011</num>
  </msg>
</messages>

Example 6-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 6-9 displays a sample stylesheet that merges the two XML documents based on matching the <key/> element values.

Example 6-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>

Create the XML files in Example 6-7, Example 6-8, and Example 6-9 and run the following at the command line:

oraxsl msg_w_num.xml msgmerge.xsl msgmerge.xml

Example 6-10 shows the output document, which merges the data contained in msg_w_num.xml and msg_w_text.xml.

Example 6-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>

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 to work with.

Creating an HTML Input Form Based on the Columns in a Table

Suppose that you want to generate an HTML form for inputting data that uses column names from a database table. You can achieve this goal by using XSU to obtain an XML document based on the user_tab_columns table and XSLT to transform the XML into an HTML form.

  1. Use XSU to generate an XML document based on the columns in the table. For example, suppose that the table is hr.employees. You can run XSU from the command line as follows:

    java OracleXML getXML -user "hr/password"\
     "SELECT column_name FROM user_tab_columns WHERE table_name = 'EMPLOYEES'"
    
  2. Save the XSU output as an XML file called emp_columns.xml. The XML should look like the following, with one <ROW> element corresponding to each column in the table (some <ROW> elements have been removed to conserve space):

    <?xml version = '1.0'?><ROWSET>
       <ROW num="1">
          <COLUMN_NAME>EMPLOYEE_ID</COLUMN_NAME>
       </ROW>
       <ROW num="2">
          <COLUMN_NAME>FIRST_NAME</COLUMN_NAME>
       </ROW>
       <!-- rows 3 through 10 -->
       <ROW num="11">
          <COLUMN_NAME>DEPARTMENT_ID</COLUMN_NAME>
       </ROW>
    </ROWSET>
    
  3. Create a stylesheet to transform the XML into HTML. For example, create the columns.xsl stylesheet as follows:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="html"/>
      <xsl:template match="/">
        <HTML>
          <xsl:apply-templates select="@*|node()"/>
        </HTML>
      </xsl:template>
      <xsl:template match="ROW">
        <xsl:value-of select="COLUMN_NAME"/>
        <xsl:text>&nbsp;</xsl:text>
        <INPUT NAME="{COLUMN_NAME}"/>
        <BR/>
      </xsl:template>
    </xsl:stylesheet>
    
  4. Run the oraxsl utility to generate the HTML form. For example:

    oraxsl emp_columns.xml columns.xsl emp_form.htm
    
  5. Review the output HTML form, which should have the following contents:

    <HTML>
       EMPLOYEE_ID&nbsp;<INPUT NAME="EMPLOYEE_ID"><BR>
       FIRST_NAME&nbsp;<INPUT NAME="FIRST_NAME"><BR>
       LAST_NAME&nbsp;<INPUT NAME="LAST_NAME"><BR>
       EMAIL&nbsp;<INPUT NAME="EMAIL"><BR>
       PHONE_NUMBER&nbsp;<INPUT NAME="PHONE_NUMBER"><BR>
       HIRE_DATE&nbsp;<INPUT NAME="HIRE_DATE"><BR>
       JOB_ID&nbsp;<INPUT NAME="JOB_ID"><BR>
       SALARY&nbsp;<INPUT NAME="SALARY"><BR>
       COMMISSION_PCT&nbsp;<INPUT NAME="COMMISSION_PCT"><BR>
       MANAGER_ID&nbsp;<INPUT NAME="MANAGER_ID"><BR>
       DEPARTMENT_ID&nbsp;<INPUT NAME="DEPARTMENT_ID"><BR>
    </HTML>