[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

Subject: Re: Identify last node in nested nodeset with same name
From: "Sam D. Chuparkoff" <sdc@xxxxxxxxxx>
Date: Sat, 25 Jun 2005 00:04:28 -0700
wrapping li
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

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.