On Thursday, January 09, 2003 5:51 PM, Jeni Tennison wrote:
But to answer your more general question, you're correct that in
unextended XSLT 1.0 you have to call templates to perform functions
and that sometimes this can lead to verbose and ungainly code.
However, most XSLT processors have a mechanism for defining extension
functions. Several support EXSLT's func:function/func:result elements,
which enable you to do:
Correct me if I'm wrong, or restarting an ancient debate, but it
strikes me that using XSLT in this way is basically "Wrong" or a Bad
Thing. I've found that usually there is a fairly simple way to avoid
procedural techniques if I conceptualize the program as being the XML
data, and think of it as the data making calls on the XSLT. In other
words, in writing XSLT I'm basically writing functions that are called
by the data, as the processor walks the tree. As far as XSLT being very
verbose, I haven't really found that to be true yet either.
Perhaps you've covered this already in your book (I haven't read any of
the XSLT books). But in reading XSLT code (not here, but in open source
projects) I often am surprised. I've attached my latest code for
transforming RNG -> HTML forms to the bottom, just in case anyone is
interested. It's a work in process, not even alpha. I'm including it
just as an illustration of how I'm using XSLT right now. (It assumes
that all RNG refs have been expanded fully (i have another XSLT to do
that) and that the RNG begins with a plain <grammar> tag.)
simon
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*" />
<xsl:output omit-xml-declaration = "yes"/>
<xsl:template match="grammar">
<div class="form">
<h1>A Form</h1>
<p>Here's a form for you. It's based on an RNG grammar.</p>
<form action="form.html" method="GET">
<xsl:apply-templates/>
<button type="reset">Reset</button>
<button type="submit">Submit</button>
</form>
<p>That's the end of the form.</p>
</div> <!--form-->
</xsl:template>
<xsl:template match="start">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="choice">
Choice:
<xsl:call-template name="simpleRecurse"/>
</xsl:template>
<xsl:template match="value">
<xsl:call-template name="radio"/>
Value could be <b><xsl:value-of select="."/></b>
</xsl:template>
<xsl:template match="group">
Group:
<xsl:call-template name="simpleRecurse"/>
</xsl:template>
<xsl:template match="optional">
<input type="checkbox">
<xsl:attribute name="name">
<xsl:call-template name="namesAttrsOfAncestors"/>
<xsl:call-template name="nameAttrOfDescendant"/>
</xsl:attribute>
</input>
<xsl:call-template name="namesAttrsOfAncestors"/>
<xsl:call-template name="nameAttrOfDescendant"/>
[
<xsl:call-template name="simpleRecurse"/>
]
</xsl:template>
<xsl:template match="zeroOrMore">
Zero or More:
<xsl:call-template name="simpleRecurse"/>
</xsl:template>
<xsl:template match="oneOrMore">
One or More:
<xsl:call-template name="simpleRecurse"/>
</xsl:template>
<xsl:template match="element">
<xsl:choose>
<xsl:when test="not(./*)"> <!--no children--><!--or ./empty-->
<ul><li>
<xsl:call-template name="labelTemplate"/>
<xsl:call-template name="inputTemplate"/>
</li></ul>
</xsl:when>
<xsl:otherwise>
<b><xsl:call-template name="namesAttrsOfAncestors"/></b>
<xsl:call-template name="simpleRecurse"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="attribute">
<xsl:choose>
<xsl:when test="not(./*) or ./empty"> <!--no children-->
<xsl:call-template name="labelTemplate"/>
<xsl:call-template name="inputTemplate"/>
</xsl:when>
<xsl:otherwise>
<b><xsl:call-template name="namesAttrsOfAncestors"/></b>
<xsl:call-template name="simpleRecurse"/>
</xsl:otherwise>
</xsl:choose> ((Attribute))
</xsl:template>
<xsl:template match="text">
<!--Text:-->
<!--[[xsl:call-template name="labelTemplate"/]]-->
<xsl:call-template name="inputTemplate"/>
(text)
<xsl:call-template name="simpleRecurse"/>
</xsl:template>
<xsl:template match="list">
List:
<xsl:call-template name="simpleRecurse"/>
</xsl:template>
<xsl:template match="data">
<xsl:call-template name="labelTemplate"/>
<xsl:call-template name="listInput"/>
(<xsl:value-of select="@type"/>)
<!--should check for param children-->
</xsl:template>
<!--******************************-->
<!--Named templates-->
<xsl:template name="nameAttrOfAncestor">
<xsl:value-of
select="ancestor-or-self::*[self::element or
self::attribute][(_at_)name][1]/@name"/>
</xsl:template>
<xsl:template name="nameAttrOfDescendant">
<xsl:value-of
select="descendant-or-self::*[self::element or
self::attribute][(_at_)name][1]/@name"/>
</xsl:template>
<xsl:template name="namesAttrsOfAncestors">
<xsl:for-each
select="ancestor-or-self::*[self::element or
self::attribute][(_at_)name]/@name">
<xsl:value-of select="."/><xsl:text>.</xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template name="simpleRecurse">
<br />
<xsl:apply-templates/>
<br />
</xsl:template>
<xsl:template name="radio">
<input type="radio">
<xsl:attribute name="name">
<xsl:call-template name="namesAttrsOfAncestors"/>
</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="."/>
</xsl:attribute>
</input>
</xsl:template>
<xsl:template name="listInput">
<input>
<xsl:if test="../choice">
<xsl:attribute name="type">radio</xsl:attribute>
<xsl:attribute name="name">
<xsl:call-template name="namesAttrsOfAncestors"/>
</xsl:attribute>
</xsl:if>
<xsl:attribute name="id">
<xsl:call-template name="namesAttrsOfAncestors"/>
</xsl:attribute>
<xsl:attribute name="value">
<xsl:call-template name="namesAttrsOfAncestors"/>
</xsl:attribute>
</input>
</xsl:template>
<xsl:template name="labelTemplate">
<label>
<xsl:attribute name="for">
<xsl:call-template name="namesAttrsOfAncestors"/>
</xsl:attribute>
<b>
<xsl:call-template name="namesAttrsOfAncestors"/>
</b>
</label>
</xsl:template>
<xsl:template name="inputTemplate">
<input>
<xsl:attribute name="name">
<xsl:call-template name="namesAttrsOfAncestors"/>
</xsl:attribute>
<xsl:attribute name="value">
<xsl:call-template name="namesAttrsOfAncestors"/>
</xsl:attribute>
</input>
</xsl:template>
<xsl:template match="define">
[Define:
<b><xsl:value-of select="@name"/></b>]
</xsl:template>
</xsl:stylesheet>
---
www.simonwoodside.com
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list