SLT 1.0 provides a way for developers to call implementation-specific extension functions from within a stylesheet. In the Oracle XSLT processor for Java, you use XSLT extension functions to access Java class functions (methods) from an XSLT stylesheet, letting you use all Java’s power to augment native XSLT transformations.
The Java methods you access from XSLT may be either static or non-static methods. This article explains how to configure XSLT extension functions, as implemented in XDK 10g, for use in an XSLT stylesheet, parsing and modifying an XML document using extension functions as an example.
Preliminary Setup
To follow along, you’ll need the Oracle command-line XSLT processor utility oracle.xml.parser.v2.oraxsl
, from the XML Developer’s Kit (XDK) 10g Production for Java, which you can download here. Extract the xdk_nt_10_1_0_2_0_production.zip
file to an installation directory of your choice. Add
to your CLASSPATH¸ where
is the directory where you extracted the .zip
file.
Parsing with XSLT Extension Functions
For this example, you can use the catalog.xml
XML document shown below (also available in the downloadable code). Copy the catalog.xml
file to a c:/catalog
directory on your hard drive:
Refactoring for PL/SQL Developers Steven Feuerstein
Typically you’d use XSLT extension functions to:
- Perform a conversion. For example you might need to convert Fahrenheit to Celsius, or perform math functions that are not included in XSLT’s library functions.
- Create XSLT variables from result values. It’s sometimes convenient to get the results of a process into an XSLT variable. Using extension functions is a natural way to achieve that.
It’s important to note that this example intentionally makes no modifications that you can’t do in standard XSLT. Instead, it focuses on demonstrating all the features of XSLT extension functions, which are:
- Use of static methods.
- Use of non static methods.
- Use of custom classes.
- Use of variables with values obtained with extension functions.
- Using constructor extension functions.
You can use standard XSLT techniques to check the transformation.
After modifying the input document with the XSLT extension features, it’ll look slightly different, as shown below. Specifically, the
Oracle Certified Master Jim Dillani
Declaring Extension Function Namespaces
To configure XSLT extension functions in an XSLT you must declare the namespace of the extension functions (Java class methods) in the XSLT Stylesheet. This example uses Java class methods from the classes:
- oracle.xml.parser.v2.DOMParser
- oracle.xml.parser.v2.XMLDocument
- oracle.xml.parser.v2.XMLPrintDriver
- org.w3c.dom.Element
- org.w3c.dom.Node
- org.w3c.dom.NodeList
xsl:stylesheet
element of the XSLT. The syntax for declaring a Java extension function namespace is:
xmlns:= "http://www.oracle.com/XSL/Transform/java/"
Using the syntax example above,
is a name you choose that you’ll later use in the stylesheet to invoke methods on the matching Java class, and
is the Java class on which you want to call the methods. For example, here are two of the namespace declarations for the classes listed above:
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"
You can see working examples of these namespace declarations in the sample XSLT file shown in Listing 1.
XSLT extension functions do not have any provision for casting Java objects; however, because many select
calls to retrieve XML DOM objects return Node objects?even though you actually want to work with an Element object?you often need to make typecasts, such as from Node to Element. To convert one class to another you need a custom Java class. The example XSLT (see Listing 1) uses the custom Java class NodeToElement.java
to cast org.w3c.dom.Node types to org.w3c.dom.Element types. Here’s the code for the NodeToElement
class:
import org.w3c.dom.*;public class NodeToElement{ public static Element nodeToElement(Node node){ Element element=null; if(node instanceof Element) element=(Element)node; return element; }}
Instantiating Java Classes
In general, the syntax to create a class object in XSLT is…
…where
is the name of the XSLT variable you will use to refer to the class object in the XSLT, and
is the namespace prefix for the Java class that you declared in the xsl:stylesheet
element of the XSLT (see the preceding section).
The param1
, param2
, param3
items in the preceding syntax represent any constructor parameters needed to create a class instance.
You can see an example in the root template of the example XSLT stylesheet, which creates a DOMParser object, using the code:
In a similar fashion, you create a java.io.File instance and a java.io.FileReader instance using this code:
Parsing the XML
Now you can parse the example XML document with the DOMParser class’s parse( java.io.Reader)
method:
The parse method is a non-static method of the DOMParser class. The syntax for a Java class non-static method in an XSLT is:
select=":(, , )"
By now this should begin to look familiar, but just to be sure:
is the namespace prefix for the Java class specified in thexsl:stylesheet
element.
is the Java class method you want to call.
is the XSLT variable representing the class instance on which you want to call the non-static method.
,
are the method parameters.
Storing Java Results in XSLT
You can place values returned from non-static methods into XSLT variables.
For example, to obtain the parsed XMLDocument and save it into the variable named parsedDocument
, you could write:
You can obtain node lists as well as individual nodes. To modify the first journal
node, first retrieve the list of journal
nodes from the parsed XML document:
Then select the first node from the list:
Because XSLT can’t cast objects (remember?) you have to convert the journal
node, which is of type org.w3c.dom.Node, to an org.w3c.dom.Element using the Java NodeToElement class’s nodeToElement(Node node)
method. You assign the result to an XSLT variable:
Note that the call was slightly different, because nodeToElement()
is a static method. The syntax for a static method in an XSLT is…
select=":(, )"
…where
is the namespace prefix for the Java class,
is the static method you’re calling, and
,
(etc.) are the static method parameters.
Modifying Attributes
To modify an element’s attributes, you first remove the attribute, and then add a new attribute and value to the element. So, for example, to change the date
attribute in the journal element, first remove it:
Then create a new attribute and add it to the journal
element:
The sample XSLT uses a similar process to modify the article
element’s section
attribute.
Modifying Element Text
To modify the text in the title element, first retrieve the title node:
Then you can modify the title node’s value directly:
Modifying the author
node follows the same steps.
Although XSLT is typically used for transforming an XML input into another format, sometimes that’s not exactly what you need. In this article, you saw how to add power to XSLT by loading an XML file and altering its contents using Java class methods from within the stylesheet itself, using the XSLT extension functions to call the Java class methods from XSLT.
Too see the sample XSLT in action, copy the sample XSLT file parser.xslt
shown in Listing 1 to a directory and run it with the command-line utility oraxsl
. The syntax of the oraxsl command is:
>oraxsl source stylesheet
To convert the example XML document run the following oraxsl command that specifies parser.xslt as a source and as the stylesheet:
> oraxsl parser.xslt parser.xslt
Extend XSLT Functions
Normally, the first parameter to oraxsl
specifies the file the stylesheet named in the second parameter will process; however, because this sample stylesheet doesn’t use a source XML document, the first parameter is irrelevant. Still, it’s required, and it has to be a valid file, so I simply used the stylesheet file again. In this case, the transformation will work identically regardless of which file you use for the first parameter.
To wrap up, you can use XSLT extension functions to extend the library of functions that XSLT provides. You can store the return values of XSLT extension functions in XSLT variables to use them in your stylesheets. Although?for demonstration purposes?this sample doesn’t reflect the rule, you should normally use XSLT extension functions only if the XSLT doesn’t provide the required functionality.