On Thu, 2005-06-23 at 19:26 -0700, Mat Bergman wrote:
I am working with XML data that shares the same
element name for each node set, for example:
<menu name="link1"/>
<menu name="link2">
<menu name="link2a"/>
<menu name="link2b"/>
</menu>
My XSL stylesheet transforms this into an HTML
unordered list, like this:
<ul>
<li>link1</li>
<li>link2
<ul>
<li>link2a</li>
<li>link2b</li>
</ul>
</li>
</ul>
I think this is a good question as asked. I noticed both of the
previous answers started by wrapping the input in a new element and
defining a template for that new node. But sometimes it is necessary
to introduce structure that isn't present in the input around a
sequence of like siblings. Wrapping li s in ul s is a good example.
Here's a solution that uses modes a little much, but tries to make the
point that one could generalize this kind of logic, though it's not
done here.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity -->
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
<!-- mode change on the first in a sequence of menu siblings -->
<xsl:template match="menu[not(preceding-sibling::*[1]/self::menu)]">
<xsl:apply-templates select="." mode="slurp"/>
</xsl:template>
<!-- spit this and, recursively, all consecutive menu siblings -->
<xsl:template match="menu" mode="swish">
<xsl:apply-templates select="." mode="spit"/>
<xsl:apply-templates select="following-sibling::*[1]/self::menu"
mode="swish"/>
</xsl:template>
<!-- here we can introduce some new structure -->
<xsl:template match="menu" mode="slurp">
<ul>
<xsl:apply-templates select="." mode="swish"/>
</ul>
</xsl:template>
<!-- a menu is translated to an li -->
<xsl:template match="menu" mode="spit">
<li>
<xsl:value-of select="@name"/>
<xsl:apply-templates/>
</li>
</xsl:template>
<!-- ignore any menu item that isn't the first in a series -->
<xsl:template match="menu"/>
</xsl:stylesheet>
Here's some input:
<root>
<random>Random text</random>
<menu name="link1"/>
<menu name="link2">
<menu name="link2a"/>
<menu name="link2b"/>
<menu name="link2c"/>
<random>Random text</random>
</menu>
<random>Random text</random>
</root>
And here's the output, with spaces added by me:
<root>
<random>Random text</random>
<ul>
<li>link1</li>
<li>
link2
<ul>
<li>link2a</li>
<li>link2b</li>
<li>link2c</li>
</ul>
<random>Random text</random>
</li>
</ul>
<random>Random text</random>
</root>
Comments/links welcome.
sdc
--~------------------------------------------------------------------
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>
--~--