Subject: Re: [xsl] Identify last node in nested nodeset with same name From: "Sam D. Chuparkoff" <sdc@xxxxxxxxxx> Date: Sat, 25 Jun 2005 00:04:28 -0700 |
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
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Identify last node in nes, Mukul Gandhi | Thread | [xsl] xsl variable to jsp public va, -= jay =- |
[xsl] Converting Child to Sibling, Arulxml | Date | Re: [xsl] Converting Child to Sibli, omprakash . v |
Month |