Solved

Site breadcrumb trail by transforming XML with XSLT

Posted on 2007-04-02
5
448 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

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Suggested Solutions

Introduction Since I wrote the original article about Handling Date and Time in PHP and MySQL (http://www.experts-exchange.com/articles/201/Handling-Date-and-Time-in-PHP-and-MySQL.html) several years ago, it seemed like now was a good time to updat…
Browsers only know CSS so your awesome SASS code needs to be translated into normal CSS. Here I'll try to explain what you should aim for in order to take full advantage of SASS.
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

758 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

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now