docs.intersystems.com
Home  /  Application Development: Additional Options  /  Using XML Tools  /  Performing XSLT Transformations


Using XML Tools
Performing XSLT Transformations
[Back]  [Next] 
InterSystems: The power behind what matters   
Search:  


XSLT (Extensible Stylesheet Language Transformations) is an XML-based language that you use to describe how to transform a given XML document into another XML or other “human-readable” document. You can use classes in the %XML.XSLT and %XML.XSLT2 packages to perform XSLT 1.0 and 2.0 transforms. This chapter discusses the following topics:
Note:
The XML declaration of any XML document that you use should indicate the character encoding of that document, and the document should be encoded as declared. If the character encoding is not declared, InterSystems IRIS uses the defaults described in Character Encoding of Input and Output,” earlier in this book. If these defaults are not correct, modify the XML declaration so that it specifies the character set actually used.
Overview of Performing XSLT Transformations in InterSystems IRIS
InterSystems IRIS provides two XSLT processors, each with its own API:
The APIs are similar for the two processors, except that methods in %XML.XSLT2 use an additional argument, to specify the gateway connection to use.
To perform XSLT transformations, do the following:
  1. If you are using the Saxon processor, configure the XSLT Gateway Server, as described in the next section. Or use the default configuration.
    The gateway is not needed if you are using the Xalan processor.
    The system automatically starts the gateway when needed. Or you can manually start it.
  2. If you are using the Saxon processor, optionally create an instance of %Net.Remote.Gateway, which represents a single connection to the XSLT Gateway.
    Note that this step is required to take advantage of compiled stylesheets and the isc:evaluate cache, when you are using the Saxon processor.
  3. Optionally create a compiled stylesheet and load it into memory. See Creating a Compiled Stylesheet,” later in this chapter. If you are using the Saxon processor, be sure to specify the gateway argument when you create the compiled stylesheet.
    This step is useful if you intend to use the same stylesheet repeatedly. This step, however, also consumes memory. Be sure to remove the compiled stylesheet when you no longer need it.
  4. Call one of the transform methods of the applicable API. If you are using the Saxon processor, optionally specify the gateway argument when you call the transform method.
    See Performing an XSLT Transform,” later in this chapter.
  5. Optionally call additional transform methods. If you are using the Saxon processor, optionally specify the gateway argument when you call the transform method; this enables you to evaluate another transform using the same connection. This transformation will have access to all compiled stylesheets and isc:evaluate cache entries associated with this connection. If you open a new connection, other connections (and their compiled stylesheets and caches) are ignored.
Studio also provides a wizard that you can use to test XSLT transformations; this is described later in this chapter.
Configuring, Starting, and Stopping the XSLT 2.0 Gateway
When you use the Saxon processor (to perform XSLT 2.0 transformations), InterSystems IRIS uses the XSLT 2.0 Gateway (which in turn uses Java). To configure this gateway:
  1. Select Go.
    The system displays the XSLT Gateway Server page.
    The left area displays configuration details, and the right area displays recent activity.
  2. In the left area, optionally specify the following settings:
    This area also displays the current value of the JAVA_HOME environment variable.
    Note that you cannot edit any of these values while the gateway is running.
  3. If you have made changes, select Save to save them. Or select Reset to discard them.
  4. Optionally select Test to test your changes.
On this page, you can also do the following:
Reusing an XSLT Gateway Server Connection (XSLT 2.0)
If you are using the Saxon processor, InterSystems IRIS uses the XSLT 2.0 Gateway, which you have previously configured. To communicate with this gateway, InterSystems IRIS internally creates an XSLT gateway connection (an instance of %Net.Remote.Gateway). By default, the system creates a connection, uses it for the transformation, and then discards the connection. There is overhead associated with opening a new connection, so maintaining a single connection for multiple transforms gives the best performance. Also, you must maintain your own connection in order to take advantage of compiled stylesheets and the isc:evaluate cache.
To reuse an XSLT gateway connection:
  1.  set status=##class(%XML.XSLT2.Transformer).StartGateway(.gateway)
    This method starts the XSLT 2.0 Gateway (if it is not already running) and returns, as output, an instance of %Net.Remote.Gateway. Note that the method also returns a status.
    The instance of %Net.Remote.Gateway represents the connection to the gateway.
  2. Check the status returned by the previous step:
     if $$$ISERR(status) {
         quit
     }
  3. Create any compiled stylesheets. When you do so, specify the gateway argument as the instance of instance of %Net.Remote.Gateway that you created in step 1.
  4. Call the transform methods of %XML.XSLT2.Transformer as needed (TransformFile(), TransformFileWithCompiledXSL(), TransformStream(), and TransformStreamWithCompiledXSL()). When you do so, specify the gateway argument as the instance of %Net.Remote.Gateway that you created in step 1.
  5. When you no longer need a given compiled stylesheet, call the ReleaseFromServer() method of %XML.XSLT2.CompiledStyleSheet:
     Set status=##class(%XML.XSLT2.CompiledStyleSheet).ReleaseFromServer(compiledStyleSheet,,gateway) 
    Important:
    Be sure to use this method when you no longer need the compiled stylesheet.
  6. When you no longer need the XSLT gateway connection, call the StopGateway() method of %XML.XSLT2.Transformer, passing the gateway connection as the argument:
     set status=##class(%XML.XSLT2.Transformer).StopGateway(gateway)
    This method discards the connection and resets the current device. It does not stop the XSLT 2.0 Gateway.
    Important:
    Be sure to use this method when you no longer need the connection.
For an example, see the method Example10() in XSLT2.Examples in the SAMPLES namespace.
Creating a Compiled Stylesheet
If you intend to use the same style sheet repeatedly, you may want to compile it to improve speed. Note that this step consumes memory. Be sure to remove the compiled style sheet when you no longer need it.
To create a compiled style sheet:
For all these methods, the complete argument list is as follows, in order:
  1. source — The style sheet.
    For CreateFromFile(), this argument is the filename. For CreateFromStream(), this argument is a stream.
  2. compiledStyleSheet — The compiled style sheet, returned as an output parameter.
    This is an instance of the style sheet class (%XML.XSLT.CompiledStyleSheet or %XML.XSLT2.CompiledStyleSheet, as appropriate).
  3. errorHandler — An optional custom error handler to use when compiling the style sheet. See Customizing the Error Handling,” later in this chapter.
    For methods in both classes, this is an instance of %XML.XSLT.ErrorHandler.
The CreateFromFile() and CreateFromStream() methods return a status, which should be checked.
For example:
 //set tXSL equal to the OREF of a suitable stream
 Set tSC=##class(%XML.XSLT.CompiledStyleSheet).CreateFromStream(tXSL,.tCompiledStyleSheet)
 If $$$ISERR(tSC) Quit
Performing an XSLT Transform
To perform an XSLT transform:
These methods have similar signatures. The argument lists for these methods are as follows, in order:
  1. pSource — The source XML, which is to be transformed. See the table after this list.
  2. pXSL — The style sheet or compiled style sheet. See the table after this list.
  3. pOutput — The resulting XML, returned as an output parameter. See the table after this list.
  4. pErrorHandler — An optional custom error handler. See Customizing the Error Handling,” later in this chapter. If you do not specify a custom error handler, the method uses a new instance of %XML.XSLT.ErrorHandler (for both classes).
  5. pParms — An optional InterSystems IRIS multidimensional array that contains parameters to be passed to the style sheet. See Specifying Parameters for Use by the Stylesheet,” later in this chapter.
  6. pCallbackHandler — An optional callback handler that defines XSLT extension functions. See Adding and Using XSLT Extension Functions,” later in this chapter.
  7. pResolver — An optional entity resolver. See Performing Custom Entity Resolution,” later in this book.
  8. (Only for %XML.XSLT2.Transformer) gateway — An optional instance of %Net.Remote.Gateway. Specify this argument if you want to reuse an XSLT Gateway connection for better performance; see Reusing an XSLT Gateway Server Connection (XSLT 2.0).”
For reference, the following table shows the first three arguments of these methods, compared side by side:
Comparison of XSLT Transform Methods
Method pSource (Input XML) pXSL (Stylesheet) pOutput(Output XML)
TransformFile() String that gives a file name String that gives a file name String that gives a file name
TransformFileWithCompiledXSLT() String that gives a file name Compiled style sheet String that gives a file name
TransformStream() Stream Stream Stream, returned by reference
TransformStreamWithCompiledXSLT() Stream Compiled style sheet Stream, returned by reference
TransformStringWithCompiledXSLT() String Compiled style sheet String that gives a file name
Examples
This section shows a couple of transformations, using the following code (but different input files):
  Set in="c:\0test\xslt-example-input.xml"
  Set xsl="c:\0test\xslt-example-stylesheet.xsl"
  Set out="c:\0test\xslt-example-output.xml"
  Set tSC=##class(%XML.XSLT.Transformer).TransformFile(in,xsl,.out)
  Write tSC 
Example 1: Simple Substitution
In this example, we start with the following input XML:
<?xml version="1.0" ?>
<s1 title="s1 title attr">
  <s2 title="s2 title attr">
    <s3 title="s3 title attr">Content</s3>
  </s2>
</s1>
And we use the following style sheet:
<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" indent="yes"/>
 
<xsl:template match="//@* | //node()">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:apply-templates select="node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="/s1/s2/s3">
<xsl:apply-templates select="@*"/>
<xsl:copy>
Content Replaced
</xsl:copy>
</xsl:template>  

</xsl:stylesheet>
In this case, the output file would be as follows:
<?xml version="1.0" encoding="UTF-8"?>
<s1 title="s1 title attr">
  <s2 title="s2 title attr">
    <s3>
Content Replaced
</s3>
  </s2>
</s1>
Example 2: Extraction of Contents
In this example, we start with the following input XML:
<?xml version="1.0" encoding="UTF-8"?>
<MyRoot>
   <MyElement No="13">Some text</MyElement>
   <MyElement No="14">Some more text</MyElement>
</MyRoot>
And we use the following style sheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1"   
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="text"
            media-type="text/plain"/>
<xsl:strip-space elements="*"/>

<!-- utilities not associated with specific tags -->
<!-- emit a newline -->
<xsl:template name="NL">
    <xsl:text>&#xa;</xsl:text>
</xsl:template>

<!-- beginning of processing -->

<xsl:template match="/">
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="MyElement">
    <xsl:value-of select="@No"/>
    <xsl:text>: </xsl:text>
    <xsl:value-of select="."/>
    <xsl:call-template name="NL"/>
</xsl:template>

</xsl:stylesheet>
In this case, the output file would be as follows:
13: Some text
14: Some more text
Additional Examples
InterSystems IRIS provides the following additional examples:
Customizing the Error Handling
When an error occurs, either XSLT processor (Xalan or Saxon) executes the error() method of the current error handler, sending a message as an argument to that method. Similarly, when a fatal error or warning occurs, the XSLT processor executes the fatalError() or warning() method, as appropriate.
For all three of these methods, the default behavior is to write the message to the current device.
To customize the error handling, you do the following:
  1. For either the Xalan or the Saxon processor, create a subclass of %XML.XSLT.ErrorHandler. In this subclass, implement the error(), fatalError(), and warning() methods as needed.
    Each of these methods accepts a single argument, a string that contains the message sent by the XSLT processor.
    These methods do not return values.
  2. Then:
Specifying Parameters for Use by the Stylesheet
To specify parameters for use by the stylesheet, you create an InterSystems IRIS multidimensional array that contains the parameter names and values. You use this array in the argument list of the transform method you use.
This multidimensional array can have any number of nodes with following structure and value:
Node Value
arrayname("parameter_name") Value of the parameter named by parameter_name
Adding and Using XSLT Extension Functions
You can create XSLT extension functions in InterSystems IRIS and then use them within your stylesheet. Specifically, your stylesheet can use one of the following functions:
By default (and as an example), the latter function reverses the characters that it receives. Typically, however, the default behavior is not used, because you implement some other behavior. To simulate multiple separate functions, you pass a selector as the first argument and implement a switch that uses that value to choose the processing to perform.
Internally, the evaluate function is implemented as a method (evaluate()) in the XSLT callback handler.
To add and use XSLT extension functions, do the following:
  1. For either the Xalan or the Saxon processor, create a subclass of %XML.XSLT.CallbackHandler. In this subclass, implement the evaluate() method as needed. See the following subsection.
  2. In the style sheet, declare the namespace to which the evaluate function belongs and use the evaluate function as needed. See the following subsection.
  3. When performing an XSLT transform, create an instance of your subclass and use it in the argument list of the transform method you use. See Performing an XSLT Transform.”
Implementing the evaluate() Method
Internally, the code that calls the XSLT processor can pass any number of positional arguments to the evaluate() method of the current callback handler, which receives them as an array that has the following structure:
Node Value
Args Number of arguments
Args(index) Value of the argument in the position index
The method has a single return value. The return value can be either:
Using evaluate in a Stylesheet
To use XSLT extension functions in an XSLT, you must declare the namespace of the extension functions in the XSLT stylesheet. For the InterSystems evaluate function, this namespace is http://extension-functions.intersystems.com or com.intersys.xsltgateway.XSLTGateway, as discussed previously.
The following example shows a style sheet that uses evaluate:
<?xml version="1.0"?>

<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
xmlns:isc="http://extension-functions.intersystems.com">

  <xsl:output method="xml" indent="yes"/>
 
  <xsl:template match="//@* | //node()">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/s1/s2/s3">
  <xsl:apply-templates select="@*"/>
  <xsl:choose>
  <xsl:when test="function-available('isc:evaluate')">
  <xsl:copy>
  <xsl:value-of select="isc:evaluate(.)" disable-output-escaping="yes"/>
  </xsl:copy>
  </xsl:when>
  <xsl:otherwise>
  <xsl:value-of select="."/>
  </xsl:otherwise>
  </xsl:choose>
  </xsl:template> 

</xsl:stylesheet>
For a closer look at this example, see the source code for the Example3() method of %XML.XSLT.Transformer.
Working with the isc:evaluate Cache
The XSLT 2.0 gateway caches evaluate function calls in the isc:evaluate cache. The default maximum size of the cache is 1000 items, but you can set the size to a different value. Also, you can clear the cache, you can dump the cache, and you can pre-populate the cache from a %List with the following format:
The cache also includes a filter list of function names that can be cached. Note the following:
Adding a function name to the filter list does not limit the size of the evaluate cache. There may be any number of calls to the same function, but with different arguments and return values. Each combination of function name and arguments is a separate entry in the evaluate cache.
You can use methods from the %XML.XSLT2.Transformer class to manipulate the evaluate cache. For details, see the class reference.
Using the XSL Transform Wizard
Studio provides a wizard that performs an XSLT transformation, which is useful when you want to quickly test a style sheet or your custom XSLT extension functions. To use this schema wizard:
  1. Specify the following required details:
  2. If you have created a subclass of %XML.XSLT.CallbackHandler that you want to use in this transformation, specify the following details:
    See Adding and Using XSLT Extension Functions,” earlier in this chapter.
  3. Select Finish.
    The bottom of the dialog box displays the transformed file. You can copy and paste from this area.
  4. To close this dialog box, select Cancel.