Kaz wrote:
And here's my index.xsl file
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes"/>
<xsl:template match="root_element">
<html>
<body>
<xsl:call-template name="unordered-list">
<xsl:with-param name="items" select="item"/>
</xsl:call-template>
</body>
</html>
</xsl:template>
<xsl:template name="unordered-list">
<xsl:param name="items" select="/.."/>
<ul>
<xsl:for-each select="$items">
<li>
<xsl:value-of select="text()"/>
<xsl:if test="item">
<xsl:call-template name="unordered-list">
<xsl:with-param name="items" select="item"/>
</xsl:call-template>
</xsl:if>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
The above produces what I want, and it seems quite solid. But is there
perhaps another (better?) way to solve this task? I'm limited to XSLT
1.0.
Yes, in fact, there is. You seem to use skills with a large resemblance
to structured programming in an imperative language (i.e., in normal
English: you define a template with a name and call it, analogous to a
function in C++/VB/Ruby/Python/PHP etc). In XSLT you give the processor
a set of nodes (xsl:apply-templates select="nodeselection") to be
applied to specified templates (xsl:template match) that match a certain
node in the set. The processor will to the math for you: it will find
the most suitable matching template and you will have to do less coding
and your code is more adaptable to change.
In general, if you find you are doing something like <xsl:if
test="somenode"> you should consider replacing it with an
<xsl:apply-templates select="somenode" />. The templates will not be
applied if the node is not there (nothing to apply), so that's an
inherent "if statement" already. Furthermore, the processor will choose
the right matching template (which you still have to write for
"somenode" of course). This looks as follows:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:template match="root_element">
<html>
<body>
<ul>
<xsl:apply-templates select="item" />
</ul>
</body>
</html>
</xsl:template>
<xsl:template match="item">
<li>
<xsl:value-of select="text()"/>
<xsl:apply-templates select="item" />
</li>
</xsl:template>
<xsl:template match="item[item]">
<li>
<xsl:value-of select="text()"/>
<ul>
<xsl:apply-templates select="item" />
</ul>
</li>
</xsl:template>
</xsl:stylesheet>
If you write a stylesheet like that, think in reverse: think by yourself
"I want an html list with <ul> elements, what is the rule that outputs a
<ul> element?". Then you look into your source and you consider that the
rule is any <item> element with a child of one or more <item> elements:
<xsl:template match="item[item]">.
Then you consider "what is the rule that outputs a <li> element?" And
your answer will likely be "with any <item> element, both the ones with
and the ones without <item> children". Which is why the <li> tags are
put inside both matches.
Finally, you want to know what to process next, after you output an <ul>
or an <li> node. In this case it is simple: all <item> children. This
results in the <xsl:apply-templates select="item" /> on both places.
You may wonder why I split the item and the item[item]. The reason is:
readability and adaptability. Now you have two places where you output
<li>, but you also have more control on how to do markup for either
case: with children or without.
I changed two other small things: the encoding (I believe it is best to
do any XML related work in UTF-8/16 unless you have compelling reasons
not to internationalize your code and/or make it more interoperable),
which should also be changed in your input, and the
'omit-xml-declaration', which has no place in an xsl:output when the
output method is "html" (html output method *never* has an xml
declaration, 'omit-xml-declaration', whatever its setting, will be ignored).
Have fun with it (and with XSLT of course)!
Cheers,
-- Abel Braaksma
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--