Xalan Extensions
Xalan is the XSL processor used within the web framework. It provides an extension mechanism
which can be used to extend standard XSL processing. The extension mechanism works well,
but is somewhat cumbersome for the following reasons:
- No support for extension libraries. Extensions must be declared whereever they are used.
- Appropriate namespace declaration is required wherever extensions are used.
- No correspondance to extension implementation. If the implementation changes, the
extension declaration must be changed accordingly
- No standard descriptor for extension usage, attributes, etc.
These issues limit the use of extensions, which is unfortunate, as they allow developers
to really customize the processing.
Example
Despite the limitations, I'll show the Xalan mechanism, as it is the foundation for
extension libraries and the java extensions. In practice, you shouldn't need to use
Xalan extensions directly, but rather use the java extension mechanism or extension
libraries. Here's how to use Xalan extensions if you need to:
[xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xalan"
xmlns:xcounter="test.org.benow.web.Counter"
extension-element-prefixes="xcounter"
version="1.0"]
[xalan:component prefix="xcounter"
elements="init incr" functions="read"]
[xalan:script lang="javaclass" src="xalan://test.org.benow.web.Counter"/]
[/xalan:component]
[xsl:template match="/"]
[xcounter:init name="index" value="1"/]
[xsl:for-each select="result/item"]
[xsl:sort select="name"/]
[p]
[xsl:text][[/xsl:text]
[xsl:value-of select="xcounter:read('index')"/]
[xsl:text]]. [/xsl:text]
[xsl:value-of select="name"/]
[/p]
[xcounter:incr name="index"/]
[/xsl:for-each]
[/xsl:template]
[/xsl:stylesheet]
The extension namespace and exclusion is defined in the stylesheet and the
xalan:component block defines the extension. It identified the
prefix, the elements and functions and defines the source to be the
test.org.benow.web.Counter java class.
The xcounter extension is then used to initialize, increment and dump a counter.
The output of the processing is:
This works well, but is cumbersome for the developer for the above reasons. Extension
libraries have been introduced to reduce the implementation overhead.
Extension Libraries
This is a demo of facililated xalan extension libraries. The grouping of Xalan extensions
as shown in
the previous section is faciltated
by the framework, so that extensions are easier to group, declare and import. By default,
there is no support for extension libraries in xalan. They cannot be
included via
xsl:include or
xsl:import and must be
defined wherever they are used. The concept of extension libraries
has been implemented as part of the BeNOW web framework.
To use an extension library, include the library in the namespace declaration for the
stylesheet. At template read time, the library will be parsed and all contents
included in the stylesheet. There are several points of note for extension libraries:
- extensions live in the
lib/java/extension/ directory (or subdirectories).
- extensions in this directory will be packaged using the package mechanism during ant jar build
- packaged extensions may be reused by having the containg jar on the classpath
- extensions must be named ext[name].xsl. If it doesn't start with'
ext or end with .xsl it will not be recognised.
- the namespace for the extension must be declared within the stylesheet declaration: ie
- The
extension-element-prefixes attribute is not required, as it
is generated during extension inclusion. The prefix in the namespace (ie counter,
as given in xmlns:counter) should correspond to the prefix in the extension
xsl
- The
xmlns:xalan="http://xml.apache.org/xalan" namespace declaration
is not needed. It will automatically be added.
- the web helper extensions defined in the web framework (ie web:service, web:actions, web:*)
are always included in pages, and need not be declared
- To see the final stylesheet after extensions have been included, turn on debugging
for the org.benow.web.path.page package.
Example
The framework automatically inserts extensions which are defined in the style
sheet namespace declaration. In this example,
xmlns:counter="extsample.xsl"
is declared in the xsl:stylesheet. The frameworks sees that
lib/xsl/extension/extsample.xsl
exists and absorbs the declarations within into the stylesheet before
transformation. The extensions declared within the referenced extension xsl can then
be used during transformation.
In this example,
extsample.xsl declares
the counter operations init, read and incr, which correspond to methods within
the
test.org.benow.web.Counter class. Additionally, templates and
other content declared in the extension xsl are also included and may be used
in support of the extension.
The output including of the counter extension is:
Automatic Java Extensions
The extension libraries are nicer, as they reduce the overhead of implementing
and reusing extensions, but they still rely on an XSL file which declares the
extensions. This file must be updated as the java source changes or as more
extensions are added.
Automatic Java extensions were added to overcome this problem. These extensions
are declared in java code only, and the Xalan extension declaration is
automatically generated. This really eases the overhead of implementing extensions,
as only a java class must be created for an extension to be usable. For this reason,
automatic Java extensions are the preferred way to implement extensions written in java.
Extensions are declared in code by implementing the Extension interface. The
class is then parsed with the following process
- The namespace of the class is determined by the containing parent package name. For
test.org.benow.web.extensions.sample.Counter the namespace is
sample which corresponds to a sample: prefix.
- The name of the extension corresponds to the class names as declared in the
extension class. The Init extension class within the
test.org.benow.web.extensions.sample.Counter
class would be referenced as sample:init.
-
Attributes and elements which serve as input to the extension correspond
to fields within the extension