|
[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: Identify last node in nested nodeset with same nam
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
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|

Cart








