OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.


Help: OASIS Mailing Lists Help | MarkMail Help



   Constructing Tree using XSLT

[ Lists Home | Date Index | Thread Index ]
  • To: xml-dev@lists.xml.org
  • Subject: Constructing Tree using XSLT
  • From: Hugo Jose Ferreira <bytter@netcabo.pt>
  • Date: Sat, 13 Sep 2003 05:00:40 +0100
  • User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5b) Gecko/20030901 Thunderbird/0.2

Hi everyone,

Could someone help me here? I'm trying to construct a graphical tree 
using XML/XSLT. Here's what I'm doing:

1. Have a XML tree structure, with the correspondent tree. i.e.:

    <treemenu title='Sample Tree'>
       <item href='test1.php' title='First Item'/>
       <item href='test2.php' title='Second Item'>
          <item href='subtest1.php' title='First Subtitle'/>
          <item href='subtest2.php' title='Second Subtitle'>
              <item href='subsubtest1.php' title='First Subsubtitle'/>
       <item href='test3.php' title='Third Item'/>

2. Do the parse using the following algorithm: Call a recursive function 
that, for each item, make the necessary blank spaces (for identantion) 
and then print the item. Here's the sample XSL:

<xsl:template match='treemenu'>
  <div class='treemenu'>
  <h1><xsl:value-of select='@title' /></h1>
    <xsl:apply-templates select='item'>
      <xsl:with-param name="depth" select="0"/>

<xsl:template match='item'>
  <xsl:param name="depth"/>
  <xsl:call-template name='makespace'>
    <xsl:with-param name="depth" select="$depth"/>
  <xsl:for-each select='.'>
    <xsl:variable name="pos" select='count(../preceding-sibling::node()) 
+ 1' />
    <xsl:variable name="total" select='count(preceding-sibling::item)' />

      <xsl:when test="count(item)">
        <img src='images\folder.gif' />
        <img src='images\page.gif' />
    <xsl:if test='@href'>
      <a href='{@href}'><xsl:value-of select='@title' /></a>
    </xsl:if><xsl:if test='not(@href)'>
      <xsl:value-of select='@title' />
    </xsl:if><br />

    <xsl:apply-templates select='item'>
      <xsl:with-param name="depth" select="$depth + 1"/>

<xsl:template name='makespace'>
  <xsl:param name="depth"/>
  <xsl:if test="$depth &gt; 0">
    <img src='images\empty.gif'/>
    <xsl:call-template name='makespace'>
      <xsl:with-param name="depth" select="$depth + (-1)"/>

So far so good. But this does not print the vertical lines that connect 
items. Why? Well, I could use the empty.gif as a vertical line. I could 
even check if the item was the last one in the list, and do an 'L' 
shaped line, and not a 'T' one. BUT, the problem is that in some cases 
there ARE no vertical lines to connect, because there are not more items 
to the bottom.

When does this happen? Simple... Whenever the parent of an item doesn't 
have any brother that follows him. How? Checking the current parent 
position of the parsing, and comparing to the total items on that level 
(I've done some variables in the main template, $pos and $total, that do 
that. So, what's the solution? Well... Probably to use a XPointer/Xpath 
expression in the 'makespace' tamplate that would check (according to 
$depth) this statement in the source XML tree, and choose the proper 
image to display. My problem is: I can't build it :) So, could anyone 
PLEEEASSSEE give me an help here? It would be very appreciated!

Also, if anyone knows a faster, cleaner and elegant way to do this and 
would like to share with me, I would be very appreciated too...

My best regards too all, and thanks in advance,

Hugo Jose Ferreira


News | XML in Industry | Calendar | XML Registry
Marketplace | Resources | MyXML.org | Sponsors | Privacy Statement

Copyright 2001 XML.org. This site is hosted by OASIS