Using XPathScript to Write XSP TagLibs
XSP is an alternative server side XML programming API. It is not a
stylesheet system though - the XSP page is executed directly without a
stylesheet. XSP was originally incorporated into the Cocoon application
framework, and AxKit included XSP capabilities because it's a very
interesting and useful tool.
One of the interesting things about XSP is the ability to write taglibs
using some form of stylesheet transformation language. A taglib is a
separate sheet of tags that have special meaning to your code. They can
execute external functions or simply be used in a similar way to
external parsed entities. Here's the classic example of a usage of a
taglib from the Cocoon documentation (slightly modified from the
original):
<xsp:page
language="Perl"
xmlns:xsp="http://www.apache.org/1999/XSP/Core"
xmlns:example="http://www.plenix.com/DTD/XSP/Example"
>
<page title="Time of Day">
<p>
To the best of my knowledge, it's now
<!-- Substitute time of day here -->
<example:time-of-day format="%y/%m/%d %r"/>
</p>
</page>
</xsp:page>
|
Here the <example:time-of-day> tag gets converted
at run time to the current time using the strftime
format specified in the format attribute.
A taglib implementation is a stylesheet that is evaluated against this
file prior to passing it to the XSP processor. The stylesheet converts
the tags that it recognises into pure XSP code (see http://xml.apache.org/cocoon/xsp.html
for more information on XSP). While this seems a rather redundant
feature, it allows even further separation between code and design.
Designers can just introduce these special tags, without worrying about
the logic behind them.
The Cocoon recommendation is to write taglibs using XSLT. This works
well, but the code often looks confusing. My recommendation for AxKit is
to use XPathScript. Here's our implementation of the time-of-day tag
using XPathScript:
<%
$t->{'xsp:page'}{prechildren} = <<EOXML;
<xsp:structure>
<xsp:include>POSIX</xsp:include>
</xsp:structure>
EOXML
$t->{'example:time-of-day'}{testcode} = sub {
my ($node, $t) = @_;
$t->{pre} =
'<xsp:expr>
POSIX::strftime("' . findvalue('@format', $node) . '", localtime)
</xsp:expr>';
return 1;
};
%>
<%= apply_templates() %>
|
This is a rather trivial example of a taglib, but hopefully it
introduces the possibilities of further extending your tag library.
In order to enable this tag library, we simply make the taglib
stylesheet the first in our stylesheet cascade:
<?xml version="1.0"?>
<?xml-stylesheet type="application/x-xpathscript" href="example.taglib"?>
<?xml-stylesheet type="application/x-xsp" href="."?>
<?xml-stylesheet type="text/xsl" href="example.xsl"?>
<xsp:page
language="Perl"
xmlns:xsp="http://www.apache.org/1999/XSP/Core"
xmlns:example="http://www.plenix.com/DTD/XSP/Example"
>
<page title="Time of Day">
<p>
To the best of my knowledge, it's now
<!-- Substitute time of day here -->
<example:time-of-day format="%y/%m/%d %r"/>
</p>
</page>
</xsp:page>
|
Note that the XSP script is executed using the stylesheet processing
instruction, with a stylesheet of ".". This stylesheet could be anything
in the case of XSP, since there is actually no stylesheet associated
with it, and the "." is merely a convention.
For comparison, here's the equivalent XSLT based taglib:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0"
xmlns:xsp="http://www.apache.org/1999/XSP/Core"
xmlns:example="http://www.plenix.com/DTD/XSP/Example"
>
<xsl:template match="xsp:page">
<xsp:page>
<xsl:copy>
<xsl:apply-templates select="@*"/>
</xsl:copy>
<xsp:structure>
<xsp:include>POSIX</xsp:include>
</xsp:structure>
<xsl:apply-templates/>
</xsp:page>
</xsl:template>
<xsl:template match="example:time-of-day">
<xsp:expr>
POSIX::strftime("<xsl:value-of select="@format"/>", localtime)
</xsp:expr>
</xsl:template>
<xsl:template match="@*|node()" priority="-1">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
</xsl:stylesheet>
|
Some people may find one version easier to work with than the other,
although I personally prefer the simplicity of XPathScript.
|