Site breadcrumb trail by transforming XML with XSLT

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!
nigelhaylerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Geert BormansInformation ArchitectCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
nigelhaylerAuthor Commented:
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
Geert BormansInformation ArchitectCommented:
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
nigelhaylerAuthor Commented:
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
Geert BormansInformation ArchitectCommented:
cheers
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Languages and Standards

From novice to tech pro — start learning today.