[FrontPage] [TitleIndex] [WordIndex

XSLT - all you ever wanted to know

(but were afraid to ask)

This page describes some xslt features, using the xalan xslt-processor, concerning the use of java classes inside xslt scripts. Most of this content was found on the following online location: http://xml.apache.org/xalan-j/extensions.html

1. Instancing java-classes

The instancing of Java-classes (instead of calling static Methods) can be fairly easy accomplished in xslt.

The first thing you have to do, is binding a prefix to your class name inside the <xsl:stylesheet> root-document:

<xsl:stylesheet xmlns:myClass="org.deegree.class.myClass">

next you can define a (local or global) xslt:variable in which you create and reference an instance of your class using the new() keyword.

<xsl:variable name="classInstance" select="myClass:new( )"/>

Methods from this java-class instance can be invoked using the following syntax

<xsl:value-of select="myClass:methodName( $classInstanz, child::* , secondMethodParam, thirdMethodParam )"/>

The first argument in the method invocation is the xsl:variable which holds the java instance. The following methodParams are the method parameters of the Method (called methodName) which will be invoked inside the java instance. This means the java class will look something like this:

package org.deegree.class;

public class MyClass{

    public String methodName( Node xsltContextNodeChildren, String first, String second ){
        //doing stuff with input params
        return second.toLowerCase();
    }

}

2. Deleting unused prefixes

While working with xslt, it might have happened to you, that you needed some prefixes from the incoming document, which were no longer present in the outgoing xml-document. Normally the xslt processor just fills in all the prefix bindings which were (re)defined inside elements or the <xsl:stylesheet> document, but do are not referenced inside the document at all for example:

<gml:Geometry xmlns:geomConv="org.deegree.framework.xml.GeometryUtils">

in which the geomConv prefix is bound to a java-class, but the prefix is never used locally, or something more global like this,

<csw:GetRecordsResponse xmlns:wfs="http://www.opengis.net/wfs" ...>

(in which the wfs prefix is not used at all in the xml doc.!! )

With the "exclude-result-prefixes" attribute inside the <xsl:stylesheet> element (e.g. the root element of the xslt-script) it is possible to remove the unused (and therefore not referenced) prefixes.

<xsl:stylesheet version="1.0"
...
...
exclude-result-prefixes="geomConv mapping wfs app fo xsl ogc" >.

The attribute values (the prefixes) must be declared inside the xslt scope (of course).

3. Finding namespacebindings in a Java class

Sometimes it is very usesful to call a java-method out of an xslt script. While invoking your method, it might be necessary to look up a namespace binding for a prefix inside the java-class. Unfortunately it is not possible to just invoke the method with an xml-node and let the deegree framework do the job, because the xslt-processor strips all namespace bindings from the xml-document. With the xalan extension jar, there is however a possibility to handle this.

The first step (again) is to define some prefix (here myClass) for your java class inside the <xsl:stylesheet> element, together with the xalan prefix, which will be used in the latter:

<xsl:stylesheet version="1.0"
...
...
xmlns:xalan="http://xml.apache.org/xalan"
xmlns:myClass="org.deegree.class.SomeClass"
>

Then you have to tell the xslt-processor that your class defines an xslt-extension, by inserting the extension-element-prefixes attribute into the <xsl:stylesheet> as well:

<xsl:stylesheet version="1.0"
...
...
xmlns:xalan="http://xml.apache.org/xalan"
xmlns:myClass="org.deegree.class.SomeClass"
extension-element-prefixes="myClass"
>

Having done this, you have to create an <xalan:component> which enables the xalan-processor to invoke any exention-methods. They differ from normal functions because they will receive only two invocation parameters (kind of an interface definition): 1. org.apache.xalan.extensions.XSLProcessorContext context //can be used to get the xslt context 2. org.apache.xalan.templates.ElemExtensionCall extElem //can be used to receive extra information on the calling process.

The <xalan:component> will have following layout:

<xalan:component prefix="myClass" elements="extensionMethodName" functions="firstMethodName secondMethodName thirdMethodName">
    <xalan:script lang="javaclass" src="xalan://org.deegree.class.SomeClass"/>
</xalan:component>

This component states the functions as well as the element extensions which can be called inside the xslt-script on the class denoted by the prefix myClass.

The only thing you'll have to do now, is calling the exentionMethodName with which you get full control over the xsl-Context inside your java-class. To invoke your method, insert the <myClass:extensionMethodName/> element some where after the first node-child in your xslt-script:

<xsl:template match="/">
  <ogc:node>
    <myClass:extensionMethodName/>
  </ogc:node>
</xsl:template>

The java class implementation will look something like this:

package org.deegree.class;

public class SomeClass{

    //the element extension method, which receives the entire xsl context.
    public void extensionMethodName( org.apache.xalan.extensions.XSLProcessorContext context,
                                     org.apache.xalan.templates.ElemExtensionCall extElem ) {
        rootNode = context.getSourceTree();
        try {
            URI  ns = XMLTools.getNamespaceForPrefix( "rim", rootNode );
        } catch ( URISyntaxException e ) {
            LOG.logError( "Couldn't get a namespace for prefix rim because: ", e );
        }
    }

    //a normal method called from the xslt script
    public String firstMethodName( Node xsltNode, String first, String second ){
        //doing stuff with input params
        return second.toLowerCase();
    }

    //a normal method called from the xslt script
    public String secondMethodName( Node xsltNode ){
        //doing stuff with input params
        return new String("bla");
    }

    //a normal method called from the xslt script
    public String thirdMethodName( String anything ){
        //doing stuff with input params
        return new String("bla");
    }
}

Before I forget, you need the xalan-java.jar (downloadable from:http://xml.apache.org/xalan-j/downloads.html ) to make this context change work.


CategoryDeegree2


2018-04-20 12:04