Solved

Site breadcrumb trail by transforming XML with XSLT

Posted on 2007-04-02
5
455 Views
Last Modified: 2013-11-18
Hi,
My site creates a XML file containing my site navigation tree. It uses parent and menu depth pointers, and I can use it to create nested unordered lists with XSLT.

Using XSL I'd also like to be able to create a breadcrumb trail as a single unordered list. Can anyone help me, or point me in the right direction? I've still got some learning to do here!

My XML takes the form of:

<?xml version="1.0"?>
<navigation siteTag="testsite">
      <mainNav>
            <navItem parent="0">
                  <navItemDocNum>72</navItemDocNum>
                  <navItemTitle>Cities</navItemTitle>
                  <navItemUrl>article.asp?art=72</navItemUrl>
                  <navItemDepth>1</navItemDepth>
            </navItem>
            <navItem parent="72">
                  <navItemDocNum>73</navItemDocNum>
                  <navItemTitle>London</navItemTitle>
                  <navItemUrl>article.asp?art=73</navItemUrl>
                  <navItemDepth>2</navItemDepth>
            </navItem>
            <navItem parent="72">
                  <navItemDocNum>74</navItemDocNum>
                  <navItemTitle>Paris</navItemTitle>
                  <navItemUrl>article.asp?art=74</navItemUrl>
                  <navItemDepth>2</navItemDepth>
            </navItem>
            <navItem parent="72">
                  <navItemDocNum>89</navItemDocNum>
                  <navItemTitle>Barcelona</navItemTitle>
                  <navItemUrl>article.asp?art=89</navItemUrl>
                  <navItemDepth>2</navItemDepth>
            </navItem>
            <navItem parent="72">
                  <navItemDocNum>94</navItemDocNum>
                  <navItemTitle>Berlin</navItemTitle>
                  <navItemUrl>article.asp?art=94</navItemUrl>
                  <navItemDepth>2</navItemDepth>
            </navItem>
            <navItem parent="94">
                  <navItemDocNum>95</navItemDocNum>
                  <navItemTitle>East v. West</navItemTitle>
                  <navItemUrl>article.asp?art=95</navItemUrl>
                  <navItemDepth>3</navItemDepth>
            </navItem>
            <navItem parent="94">
                  <navItemDocNum>96</navItemDocNum>
                  <navItemTitle>The Berlin Wall</navItemTitle>
                  <navItemUrl>article.asp?art=96</navItemUrl>
                  <navItemDepth>3</navItemDepth>
            </navItem>
            <navItem parent="94">
                  <navItemDocNum>97</navItemDocNum>
                  <navItemTitle>Hotels in Berlin</navItemTitle>
                  <navItemUrl>article.asp?art=97</navItemUrl>
                  <navItemDepth>3</navItemDepth>
            </navItem>
            <navItem parent="97">
                  <navItemDocNum>98</navItemDocNum>
                  <navItemTitle>Hotel Splendid</navItemTitle>
                  <navItemUrl>article.asp?art=98</navItemUrl>
                  <navItemDepth>4</navItemDepth>
            </navItem>
            <navItem parent="0">
                  <navItemDocNum>120</navItemDocNum>
                  <navItemTitle>Travel Options</navItemTitle>
                  <navItemUrl>article.asp?art=120</navItemUrl>
                  <navItemDepth>1</navItemDepth>
            </navItem>
      </mainNav>
</navigation>

For example - Suppose, I'm at article no. 98 (Hotel Splendid) - I'd like to be able to produce a breadcrumb trail that would give me:

Cities > Berlin > Hotels in Berlin > Hotel Splendid

in the form of a <ul></ul>.


Many thanks, any help appreciated!
0
Comment
Question by:nigelhayler
  • 3
  • 2
5 Comments
 
LVL 60

Accepted Solution

by:
Geert Bormans earned 250 total points
ID: 18836435
That would be something like this

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   
    <xsl:key name="nav-by-item" match="navItem" use="navItemDocNum"/>
   
    <xsl:param name="thisNav">98</xsl:param>
   
    <xsl:template match="navItem">
        <xsl:if test="navItemDocNum = $thisNav">
            <ul>
                <xsl:call-template name="getBreadC">
                    <xsl:with-param name="thisID" select="navItemDocNum"></xsl:with-param>
                </xsl:call-template>
            </ul>
        </xsl:if>
    </xsl:template>
   
    <xsl:template name="getBreadC">
        <xsl:param name="thisID" />
         <xsl:param name="thisNode" select="key('nav-by-item', $thisID)" />
        <xsl:if test="key('nav-by-item', $thisNode/@parent)">
            <xsl:call-template name="getBreadC">
                <xsl:with-param name="thisID" select="$thisNode/@parent"></xsl:with-param>
            </xsl:call-template>
        </xsl:if>
        <li><xsl:value-of select="$thisNode/navItemTitle"/></li>

    </xsl:template>
</xsl:stylesheet>

The recursive function starts building the breadcrump in reverse order, based on the parent id
The key is just there to find nodes efficiently based on their ID

cheers

Geert
0
 

Author Comment

by:nigelhayler
ID: 18836837
Many thanks Geert -  that's just the job!
Now I'm off to work through it, to understand just how you achieved it - I'm keen to understand this fully!

cheers
Nige
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 18836944
don't hesitate to ask questions if you don't get it fully

The key concepts are the xsl:key (which simply creates an index)
I do that to index the fields just in case you have many navigation items
If you create a key, you can use the XPath key() function to retrieve a node based on this index

and the recursive function,
which simply checks whether there is an existing parent node,and if there is, call the recursive function again, this time with the parent nodes as the parameter
This way you go up until there is no longer a valid parent node
by outputing the <li> after calling the recursive function,
you get the list in reverse order of calling
this way you can work up to the top, stil get the first processed nodes listed after the next one

hope this helps,

Cheers

geert
0
 

Author Comment

by:nigelhayler
ID: 18841921
Geert -
Thanks for that explanation. For me the recursive function using the key took some thinking about - but I get it now! It's very neat. After a slow start I'm beginning to enjoy xslt now, it's a constant source of surprise how unexpectedly flexible it's making the system I'm building.

all the best
Nige
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 18842073
cheers
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Most of the sites are being standardized with W3C Web Standards. W3C provides lot of web standard services to the web. They have the web specification, process and documentation for all the web standards. You can apply HTML, CSS and Accessibility st…
What is Node.js? Node.js is a server side scripting language much like PHP or ASP but is used to implement the complete package of HTTP webserver and application framework. The difference is that Node.js’s execution engine is asynchronous and event…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:
The viewer will learn the benefit of using external CSS files and the relationship between class and ID selectors. Create your external css file by saving it as style.css then set up your style tags: (CODE) Reference the nav tag and set your prop…

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question