RE: RE: [xsl] XPath question

Subject: RE: RE: [xsl] XPath question
From: cknell@xxxxxxxxxx
Date: Tue, 04 Feb 2003 10:37:23 -0500
[Andy Cups, David Carlisle, Michael Kay]

Thanks for your contributions, but upon further reflection, 
this approach is going to be just as complicated, if not more, 
as the recursive calling of a template with passing the id attribute 
of the parent node as a parameter that I had bee trying. The template
is in the [Zack Brown] section of the reply.

I had come up with <xsl:value-of select="count(../preceding-sibling)" />,
but in the template I used, the result was always 0, so while I did have
a valid syntax, it appears I had applied it in the wrong context.
-----------------------------------------
[David Carlisle]
> you may prefer to to just generate your 1.2.3 number directly using
> <xsl:number/>

Thanks. I've started working on that approach. The Oracle XSLT processor 
I am constrained to use inserts a gratuitous space at the end of the 
number so that this template:
<xsl:variable name="id"><xsl:number level="multiple" format="01" /></xsl:variable>

produces output such that when I insert the variable in an id attribute:

<div id="m.{$id}">

I get a result like this:
<div id="m.01 ">

So I'm for a way to clear that up.
-----------------------------------------
[Zack Brown]

> It seems like an interesting problem. Could you post 
> the precise output you'd like to see after running the 
> below input through the xslt processor?

Note that in the actual output, the id numbers in the <div> with
the class value of "sub-menu" and title of "Apples" are wrong in
the third position. The should read "(s)m.02.02 ...", instead they
read "(s)m.02.01 ...".

XML document:
=============
<menu>
  <item title="Vegetables">
    <item title="tubers">
      <item title="potatoes">
        <item>Idaho</item>
        <item>Maine</item>
        <item>Russet</item>
        <item>Yam</item>
      </item>
    </item>
  </item>
  <item title="Fruits">
    <item>Peaches</item>
    <item title="Apples">
      <item>Fuji</item>
      <item>Granny Smith</item>
      <item>Rome</item>
    </item>
  </item>
  <item>Milk</item>
</menu>

Desired output:
==============
<div id="menu-tree">
   <div id="menu" class="main-menu">
      <div id="mnu.01" class="menu-item">Vegetables</div>
      <div id="mnu.02" class="menu-item">Fruits</div>
      <div id="mnu.03" class="menu-item">Milk</div>
   </div>
   <div class="sub-menu" title="Vegetables" id="sm.01">
      <div id="m.01.01" class="sub-menu-item">tubers</div>
   </div>
   <div class="sub-menu" title="tubers" id="sm.01.01">
      <div id="m.01.01.01" class="sub-menu-item">potatoes</div>
   </div>
   <div class="sub-menu" title="potatoes" id="sm.01.01.01">
      <div id="m.01.01.01.01" class="sub-menu-item">Idaho</div>
      <div id="m.01.01.01.02" class="sub-menu-item">Maine</div>
      <div id="m.01.01.01.03" class="sub-menu-item">Russet</div>
      <div id="m.01.01.01.04" class="sub-menu-item">Yam</div>
   </div>
   <div class="sub-menu" title="Fruits" id="sm.02">
      <div id="m.02.01" class="sub-menu-item">Peaches</div>
      <div id="m.02.02" class="sub-menu-item">Apples</div>
   </div>
   <div class="sub-menu" title="Apples" id="sm.02.02">
      <div id="m.02.02.01" class="sub-menu-item">Fuji</div>
      <div id="m.02.02.02" class="sub-menu-item">Granny Smith</div>
      <div id="m.02.02.03" class="sub-menu-item">Rome</div>
   </div>
</div>

Almost there XSL:
=================
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  <xsl:output method="html" indent="yes" encoding="UTF-8" />
  <xsl:strip-space elements="*" />

  <xsl:template match="/">
    <div id="menu-tree">
      <xsl:apply-templates />
    </div>
  </xsl:template>

  <xsl:template match="menu">
    <div id="menu" class="main-menu">
      <xsl:apply-templates mode="main-menu" />
    </div>
    <xsl:call-template name="sub-menu">
      <xsl:with-param name="items" select="item[item]" />
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="sub-menu">
    <xsl:param name="items" />
    <xsl:param name="pid" select="''" />
    <xsl:for-each select="$items">
      <xsl:variable name="parent-id">
        <xsl:choose>
          <xsl:when test="string-length($pid)=0">
            <xsl:choose>
              <xsl:when test="string-length(count(preceding-sibling::item)+1)=1">sm.0<xsl:value-of select="count(preceding-sibling::item)+1" /></xsl:when>
              <xsl:otherwise>sm.<xsl:value-of select="count(preceding-sibling::*)+1" /></xsl:otherwise>
            </xsl:choose>
          </xsl:when>
          <xsl:otherwise>
            <xsl:choose>
              <xsl:when test="string-length(string(position()))=1"><xsl:value-of select="$pid" />.0<xsl:value-of select="position()" /></xsl:when>
              <xsl:otherwise><xsl:value-of select="$pid" />.<xsl:value-of select="position()" /></xsl:otherwise>
            </xsl:choose>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>

      <div class="sub-menu" title="{@title}" id="{$parent-id}">
        <xsl:apply-templates mode="sub-menu-item">
          <xsl:with-param name="pid" select="$parent-id" />
        </xsl:apply-templates>
      </div>
      <xsl:call-template name="sub-menu">
        <xsl:with-param name="items" select="item[item]" />
        <xsl:with-param name="pid" select="$parent-id" />
      </xsl:call-template>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="menu/item[item]" mode="main-menu">
    <xsl:variable name="id">
      <xsl:choose>
        <xsl:when test="string-length(string(position()))=1">mnu.0<xsl:value-of select="position()" /></xsl:when>
        <xsl:otherwise><xsl:value-of select="position()" /></xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <div id="{$id}" class="menu-item"><xsl:value-of select="@title" /></div>
  </xsl:template>

  <xsl:template match="menu/item[not(item)]" mode="main-menu">
    <xsl:variable name="id">
      <xsl:choose>
        <xsl:when test="string-length(string(position()))=1">mnu.0<xsl:value-of select="position()" /></xsl:when>
        <xsl:otherwise>m.<xsl:value-of select="position()" /></xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <div id="{$id}" class="menu-item"><xsl:value-of select="." /></div>
  </xsl:template>

  <xsl:template match="item[item]" mode="sub-menu-item">
    <xsl:param name="pid" select="''" />
    <xsl:variable name="id">
      <xsl:choose>
        <xsl:when test="$pid = ''">
          <xsl:choose>
            <xsl:when test="string-length(string(position()))=1">0<xsl:value-of select="position()" /></xsl:when>
            <xsl:otherwise><xsl:value-of select="position()" /></xsl:otherwise>
          </xsl:choose>
        </xsl:when>
        <xsl:otherwise>
          <xsl:choose>
            <xsl:when test="string-length(string(position()))=1"><xsl:value-of select="substring($pid,2)" />.0<xsl:value-of select="position()" /></xsl:when>
            <xsl:otherwise><xsl:value-of select="substring($pid,2)" />.<xsl:value-of select="position()" /></xsl:otherwise>
          </xsl:choose>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <div id="{$id}" class="sub-menu-item"><xsl:value-of select="@title" /></div>
  </xsl:template>

  <xsl:template match="item[not(item)]" mode="sub-menu-item">
    <xsl:param name="pid" select="''" />
    <xsl:variable name="id">
      <xsl:choose>
        <xsl:when test="$pid = ''">
          <xsl:choose>
            <xsl:when test="string-length(string(position()))=1">0<xsl:value-of select="position()" /></xsl:when>
            <xsl:otherwise><xsl:value-of select="position()" /></xsl:otherwise>
          </xsl:choose>
        </xsl:when>
        <xsl:otherwise>
          <xsl:choose>
            <xsl:when test="string-length(string(position()))=1"><xsl:value-of select="substring($pid,2)" />.0<xsl:value-of select="position()" /></xsl:when>
            <xsl:otherwise><xsl:value-of select="substring($pid,2)" />.<xsl:value-of select="position()" /></xsl:otherwise>
          </xsl:choose>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <div id="{$id}" class="sub-menu-item">
      <xsl:choose>
        <xsl:when test="string-length(@uri) != 0">
          <a href="{@uri}"><xsl:value-of select="." /></a>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="." />
        </xsl:otherwise>
      </xsl:choose>
    </div>
  </xsl:template>

</xsl:stylesheet>

Actual Output:
==============
<div id="menu-tree">
   <div id="menu" class="main-menu">
      <div id="mnu.01" class="menu-item">Vegetables</div>
      <div id="mnu.02" class="menu-item">Fruits</div>
      <div id="mnu.03" class="menu-item">Milk</div>
   </div>
   <div class="sub-menu" title="Vegetables" id="sm.01">
      <div id="m.01.01" class="sub-menu-item">tubers</div>
   </div>
   <div class="sub-menu" title="tubers" id="sm.01.01">
      <div id="m.01.01.01" class="sub-menu-item">potatoes</div>
   </div>
   <div class="sub-menu" title="potatoes" id="sm.01.01.01">
      <div id="m.01.01.01.01" class="sub-menu-item">Idaho</div>
      <div id="m.01.01.01.02" class="sub-menu-item">Maine</div>
      <div id="m.01.01.01.03" class="sub-menu-item">Russet</div>
      <div id="m.01.01.01.04" class="sub-menu-item">Yam</div>
   </div>
   <div class="sub-menu" title="Fruits" id="sm.02">
      <div id="m.02.01" class="sub-menu-item">Peaches</div>
      <div id="m.02.02" class="sub-menu-item">Apples</div>
   </div>
   <div class="sub-menu" title="Apples" id="sm.02.01">
      <div id="m.02.01.01" class="sub-menu-item">Fuji</div>
      <div id="m.02.01.02" class="sub-menu-item">Granny Smith</div>
      <div id="m.02.01.03" class="sub-menu-item">Rome</div>
   </div>
</div>

-- 
Charles Knell
cknell@xxxxxxxxxx - email


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread