Friday, August 04, 2006

Separating breadcrumb (homeward path) navigation from content using XML/XSL

My experiments with SiteMesh got me thinking about how best to separate out breadcrumb like navigation from the core application content. Strictly speaking I mean Homeward Path navigation rather than the form of breadcrumb navigation that essentially gives you an onscreen potted browser history.

I have seen numerous approaches to this kind of navigation. The custom JSP tag libraries for this kind of thing that I have seen have never felt quite right. In my travels I recently discovered something called JATO (also known as Sun Java System Application Framework). JATO seems to have been around for a long while but I hadn't seen it before because it appears that it was only distributed as part of the Sun ONE Application Server (formerly iPlanet Application Server). JATO seems to be a MVC framework that existed before the JSTL, Struts, JSF and Spring era.

One of the examples in the JATO sample application is of a Static Breadcrumb method.

I liked the example but not the implementation. So I thought to myself, I can do better than that! What I have ended up with is a very simple and consequently quite satisfying solution. Using the navigationSample.xml from the JATO sample application, I have achieved the same result through a fairly simple XSL transformation. This is achieved with bog standard JSTL without the need to write any new tag libraries. You could easily extend the navigation xml sitemap to include more link information and if you were using SiteMesh you could also take advantage of any "Where Am I?" information passed from your content pages.

Here is JATO's navigationSample.xml as used in the JATO sample application.

<?xml version="1.0" encoding="UTF-8"?>
<category name="Performing Arts" id="0">
<category name="Acting" id="2">
<category name="Actors" id="20">
<category name="Buster Keaton" id="200"/>
<category name="Charlie Chaplin" id="201"/>
<category name="WC Fields" id="202"/>
<category name="Actresses" id="21">
<category name="Mae West" id="210"/>
<category name="Bette Davis" id="211"/>
<category name="Marlene Dietrich" id="212"/>
<category name="Companies" id="22"/>
<category name="Circus Arts" id="3">
<category name="Acrobatics" id="30">
<category name="Anti-Gravity" id="300"/>
<category name="Human Design" id="301"/>
<category name="Trixy's Arco Page" id="302"/>
<category name="Clowning" id="31">
<category name="Rodeo Clowns" id="310">
<category name="One Eyed Jack" id="3100"/>
<category name="Cool Nite Rodeo" id="3101"/>
<category name="Creepy Clowns" id="311">
<category name="Creepy Clown Gallery" id="3110"/>
<category name="Ghost Town Clowns" id="3111"/>
<category name="Anti-Clowns" id="312">
<category name="The No Clown Zone" id="3120"/>
<category name="The Anti-Clown Page" id="3121"/>

Here is my simple JSP which currently does the XML/XSL transformation and passes any appropriate parameters into the XSL. It could of cource be optimized for performance, e.g. caching the XSL or XML in memory.

<%@taglib uri="" prefix="c"%><%--
<%@taglib uri="" prefix="x"%><%--
<c:import url="navigationSample.xml" var="xml"/><%--
<c:import url="navigation.xsl" var="xsl"/><%--
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<html xmlns="">
<style type="text/css">
body {
font-family: helvetica;
font-size: 0.8em;
<c:when test="${empty}"><%--
<x:transform xml="${xml}" xslt="${xsl}"/><%--
<x:transform xml="${xml}" xslt="${xsl}"><%--
<x:param name="id" value="${}"/><%--

Here is my navigation.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="">
<xsl:output method="xml" version="1.0" omit-xml-declaration="yes" />
<xsl:param name="id" select="'0'"/>
<xsl:strip-space elements="category"/>

<xsl:template match="/">

<xsl:template match="category[@id = $id]">
<xsl:for-each select="ancestor::category">
<xsl:attribute name="href">?id=<xsl:value-of select="@id"/></xsl:attribute>
<xsl:value-of select="@name"/>
</a> &gt;
<xsl:attribute name="href">?id=<xsl:value-of select="@id"/></xsl:attribute>
<xsl:value-of select="@name"/>
<xsl:if test="count(category) &gt; 0">
<xsl:for-each select="category">
<xsl:attribute name="href">?id=<xsl:value-of select="@id"/></xsl:attribute>
<xsl:value-of select="@name"/>


And that is all you need, horribly simple eh? I hope so.

Technically there is nothing stopping us doing XSL transformations for navigation in the client. This emergent navigation seems to be the direction that Web 2.0 applications are going. Although what stops me doing this now is all the cross browser XSL transformation issues and accessibility issues of needing to support non-javascript driven solutions on the client.


Mark McLaren said...

Doesn't work due to [@id=$id] expression
Note: Comment imported. Original by Adrian at 2008-03-07 10:57

Mark McLaren said...

I suppose it depends on your XSLT engine, it works in Xalan. I'm sorry it doesn't work for you Adrian.
Note: Comment imported. Original by markmc website: at 2008-03-26 19:12

Mark McLaren said...


It works with

Note: Comment imported. Original by Claud at 2008-07-09 18:14

for ict 99 said...

The effectiveness of IEEE Project Domains depends very much on the situation in which they are applied. In order to further improve IEEE Final Year Project Domains practices we need to explicitly describe and utilise our knowledge about software domains of software engineering Final Year Project Domains for CSE technologies. This paper suggests a modelling formalism for supporting systematic reuse of software engineering technologies during planning of software projects and improvement programmes in Final Year Project Centers in Chennai.

Spring Framework has already made serious inroads as an integrated technology stack for building user-facing applications. Spring Framework Corporate TRaining the authors explore the idea of using Java in Big Data platforms.
Specifically, Spring Framework provides various tasks are geared around preparing data for further analysis and visualization. Spring Training in Chennai

madin said...

For his Palace Nights collection,replica boots Christian Louboutin takes inspiration replica Boat Shoe from cabaret nights at Folies Bergère back in the 80s (one of his favourite haunts at the time). These Jeres courts are set on a lofty stiletto heel and structured from supple calfskin leather. The wide ankle strap criss-crosses at the front, with large, sparkling sequins that nod to the disco balls of the era. Slip them on with a tee and a silk slip to carry your look through to the evening.