6 Using the XSLT Processor for Java

This chapter explains how to use the Extensible Stylesheet Language Transformation (XSLT) processor for Java.

Topics:

Introduction to the XSLT Processor

Topics:

Prerequisites

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:

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 here:

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 here:

The Oracle XML Developer's Kit (XDK) XSLT processor implements both the XSLT and XPath 1.0 standards, and also 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 here:

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

See Also:

Chapter 33, "Oracle XML Developer's Kit Standards" for a summary of the standards supported by XDK

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 style sheet:

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

    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 XDK XSLT processor transforms an XML document into another text-based document, with a format such as XML, HTML, XHTML, or text. You can invoke the processor programmatically by using a application programming interface (API) or run it from the command line. The XSLT processor can perform these tasks:

  • Reads one or more XSLT style sheets. The processor can apply multiple style sheets to a single XML input document and generate different results.

  • Reads one or more input XML documents. The processor can use a single style sheet to transform multiple XML input documents.

  • Builds output documents by applying the rules in the style sheet 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 style sheet to perform the transformation, the XDK Java implementation of the XSLT processor can use SAX to create a style sheet object to perform transformations with higher efficiency and fewer resources. You can reuse this style sheet object to transform multiple documents without reparsing the style sheet.

Topics:

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 style sheet is match.xsl.

match.xsl

A sample style sheet 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 style sheet is math.xsl.

math.xsl

A sample style sheet for use with math.xml. The style sheet 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 style sheet for us with number.xml. The style sheet 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 style sheet is position.xsl.

position.xsl

A sample style sheet for use with position.xml. The style sheet 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 style sheet for us with reverse.xml. The style sheet 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 style sheet is string.xsl.

string.xsl

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

style.txt

A style sheet that provides the framework for an HTML page. The style sheet 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 style sheet is variable.xsl.

variable.xsl

A style sheet for use with variable.xml. The style sheet 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 style sheet. This program builds the result of XSL transformations as a DocumentFragment and does not show xsl:output features.

Run this program with any XSLT style sheet 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 style sheet. 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 style sheets in the directory.


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

  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 XDK for Java 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 style sheet. 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:

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

Using the XSLT Processor Command-Line Utility

XDK includes oraxsl, which is a command-line Java interface that can apply a style sheet 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 style sheet, 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 style sheet, then use the -l or -d options 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, must be processed, then change this behavior by setting -l and specifying the files that must 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 to be excluded. Use this option with -d. The program does not select any files with the specified extension.

-i source_extension

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

-s stylesheet

Specifies the style sheet. If you set -d or -l, then set -s to indicate the style sheet 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 enables you to specify a directory for the results.

-o result_directory

Specifies the directory in which to place results. You must set this option 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. 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 style sheets 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 style sheet 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 this 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

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

Use these 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 style sheets. This code fragment from XSL2Sample.java shows how to instantiate a parser:

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

    By default, the parser does not preserve white space unless a DTD is used. It is important to preserve white space because it enables XSLT white space rules to determine how white space is handled.

  2. Parse the XSLT style sheet with the DOMParser.parse() method. this code fragment from XSL2Sample.java shows 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. this code fragment from XSL2Sample.java shows how to perform the parse:

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

    • java.io.Reader

    • java.io.InputStream

    • XMLDocument

    • java.net.URL

    For example, XSL2Sample.java shows how to create a style sheet 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 invokes the showWarnings() and setErrorStream() methods:

    processor.showWarnings(true);
    processor.setErrorStream(System.err);
    
  6. Use the XSLProcessor.processXSL() method to apply the style sheet to the input XML data document. Table 6-3 lists some 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 style sheet.

    setEntityResolver()

    Sets an entity resolver for any relative references in the style sheet.

    setLocale()

    Sets a locale for error reporting.


    This code fragment from XSL2Sample.java shows how to apply the style sheet 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.

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

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

Getting DOM 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 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 6-4 lists some XMLDocumentFragment methods 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

Topics:

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 style sheet 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 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 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 the Java method is a nonstatic 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 style sheet.

Example 6-4 Using a Static Function in an XSLT Style Sheet

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

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 Style Sheet

<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 style sheet 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

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 style sheet 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:

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

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. For example, you might want to merge the XML documents shown 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 style sheet 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 this 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.

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.

  1. Use XSU to generate an XML document based on the columns in the table. For example, using the table hr.employees, you can run XSU from the command line:

    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 looks like this, 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 style sheet to transform the XML into HTML. For example, create the columns.xsl style sheet:

    <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 has contents similar to these:

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