title: Generate a breadcrumb trail with xsl from a node structure
body: <p>I have difficulties to write a template that generates a breadcrumb trial out of a node structure. It is not working correctly up to now, there is some flaw in my thinking how it should walk the <strong>item</strong> path.</p>
  
  <p>Consider the following page structure:</p>
  
  <pre><code>&lt;!-- ===== SITE PAGE STRUCTURE ===================================== --&gt;
  &lt;index&gt;
     &lt;item section="home" id="index"&gt;&lt;/item&gt;
     &lt;item section="service" id="index"&gt;
        &lt;item id="content-management-systems"&gt;
           &lt;item id="p1-1"/&gt;
           &lt;item id="p1-2"/&gt;
           &lt;item id="p1-3"/&gt;
        &lt;/item&gt;
        &lt;item id="online-stores"&gt;&lt;/item&gt;
        &lt;item id="search-engines-and-ir"&gt;&lt;/item&gt;
        &lt;item id="web-applications"&gt;&lt;/item&gt;
     &lt;/item&gt;
  
     &lt;item section="solutions" id="index"&gt;
        &lt;item id="document-clustering"&gt;&lt;/item&gt;
     &lt;/item&gt;
     &lt;item section="company" id="index"&gt;
        &lt;item section="company" id="about"&gt;&lt;/item&gt;
        &lt;item section="company" id="philosophy" &gt;&lt;/item&gt;
        ...
     &lt;/item&gt;
  ...
  &lt;/item&gt;
  </code></pre>
  
  <p>This site index represents a site-structure of xml content pages in its hierarchy (consider it to be a menu). It contains of <em>sections</em>, that represent the site sections just as <em>home, company, service, solutions</em>, etc. These sections can contain <em>sub-sections</em> with pages, or just regular content pages. A content page (its xml contents such as title, text content, etc) is identified by the @id attribute in the item tree. The @id attribute mainly is used to fetch the content of the entire page that will be rendered to html. 
  The breadcrumb template uses the <em>item</em> node @id attribute to get the title of the page (which will be shown in the breadcrumb trail).</p>
  
  <p>I try to implement the following template that <em>walks</em> the tree by checking the target section attribute @section and the target page attribute @id in the tree. I expect it to walk the axis down until the target item_target is found by comparing the ancestors @section attribute and the @id with $item_target of each node in that axis.</p>
  
  <p>For example: Attribute *$item_section=service* and the page id *target item_target=p1-1* should now recursively "walk" to the <em>section</em> branch "<strong>service</strong>" (depth 1), check if the target page @id is found on this level. In this case it is not found, so it makes the next recurive call (via apply-templates) to the next <em>item</em> node level (in this case it would be <strong>content-management-systems</strong>, there the target item page p1-1 is found, so the trail process is finished:</p>
  
  <p>The result should like this:</p>
  
  <p><strong>home >> service >> content management systems >> p1-1</strong></p>
  
  <p>But unfortunately it is not working correct, at least not in every case. Also maybe it can be solved more easily. I try to implement it as an recursive template that walks from the top (level 0) to the target page (item node) as a leaf.</p>
  
  <pre><code>    &lt;!-- walk item path to generate a breadcrumb trail --&gt;
      &lt;xsl:template name="breadcrumb"&gt;
          &lt;a&gt;
              &lt;xsl:attribute name="href"&gt;
                  &lt;xsl:text&gt;/&lt;/xsl:text&gt;
                  &lt;xsl:value-of select="$req-lg"/&gt;
                  &lt;xsl:text&gt;/home/index&lt;/xsl:text&gt;
              &lt;/xsl:attribute&gt;
              &lt;xsl:value-of select="'Home'"/&gt;
          &lt;/a&gt;
  
          &lt;xsl:apply-templates select="$content/site/index" mode="Item-Path"&gt;
              &lt;xsl:with-param name="item_section" select="'service'"/&gt;
              &lt;xsl:with-param name="item_target" select="'search-engines-and-ir'"/&gt;
              &lt;xsl:with-param name="depth" select="0"/&gt;
          &lt;/xsl:apply-templates&gt;
      &lt;/xsl:template&gt;
  
      &lt;xsl:template match="item" mode="Item-Path"&gt;
          &lt;xsl:param name="item_section" /&gt;
          &lt;xsl:param name="item_target" /&gt;
          &lt;xsl:param name="depth" /&gt;
          &lt;!--
          depth=&lt;xsl:value-of select="$depth"/&gt;
          count=&lt;xsl:value-of select="count(./node())"/&gt;&lt;br/&gt;
  --&gt;
          &lt;xsl:variable name="cur-id" select="@id"/&gt;
          &lt;xsl:variable name="cur-section" select="@section"/&gt;
          &lt;xsl:choose&gt;    
              &lt;xsl:when test="@id=$item_target"&gt;
                  &amp;gt;&amp;gt;
                  &lt;a&gt;
                      &lt;xsl:attribute name="href"&gt;
                          &lt;xsl:text&gt;/&lt;/xsl:text&gt;
                                              &lt;!-- req-lg: global langauge variable --&gt;
                          &lt;xsl:value-of select="$req-lg"/&gt;
                          &lt;xsl:text&gt;/&lt;/xsl:text&gt;
                          &lt;xsl:value-of select="$item_section"/&gt;
                          &lt;xsl:text&gt;/&lt;/xsl:text&gt;
                          &lt;xsl:if test="$depth = 2"&gt;
                              &lt;xsl:value-of select="../@id"/&gt;
                              &lt;xsl:text&gt;/&lt;/xsl:text&gt;
                          &lt;/xsl:if&gt;
                          &lt;xsl:value-of select="@id"/&gt;
                      &lt;/xsl:attribute&gt;
                      &lt;xsl:value-of 
                          select="$content/page[@id=$cur-id]/title"/&gt;
                  &lt;/a&gt;
              &lt;/xsl:when&gt;
              &lt;xsl:otherwise&gt;
                  &lt;xsl:if test="ancestor-or-self::item/@section = $item_section and count(./node()) &gt; 0"&gt;
                  &amp;gt;&amp;gt;:
                  &lt;a&gt;
                      &lt;xsl:attribute name="href"&gt;
                          &lt;xsl:text&gt;/&lt;/xsl:text&gt;
                                              &lt;!-- req-lg: global langauge variable --&gt;
                          &lt;xsl:value-of select="$req-lg"/&gt;
                          &lt;xsl:text&gt;/&lt;/xsl:text&gt;
                          &lt;xsl:value-of select="$item_section"/&gt;
                          &lt;xsl:text&gt;/&lt;/xsl:text&gt;
                          &lt;xsl:if test="$depth = 2"&gt;
                              &lt;xsl:value-of select="../@id"/&gt;
                              &lt;xsl:text&gt;/&lt;/xsl:text&gt;
                          &lt;/xsl:if&gt;
                          &lt;xsl:value-of select="@id"/&gt;
                      &lt;/xsl:attribute&gt;
                      &lt;xsl:value-of 
                          select="$content/page[@id=$cur-id and @section=$item_section]/title"/&gt;
                  &lt;/a&gt;
                  &lt;/xsl:if&gt;
              &lt;/xsl:otherwise&gt;
          &lt;/xsl:choose&gt;
  
          &lt;xsl:apply-templates select="item" mode="Item-Path"&gt;
              &lt;xsl:with-param name="item_section" select="$item_section"/&gt;
              &lt;xsl:with-param name="item_target" select="$item_target"/&gt;
              &lt;xsl:with-param name="depth" select="$depth + 1"/&gt;
          &lt;/xsl:apply-templates&gt;
  
      &lt;/xsl:template&gt;
  </code></pre>
  
  <p>So as the hardcoded parameters in the template <strong>breadcrumb</strong>, target section = 'service' and target page = 'search-engines-and-ir', I expect an output like</p>
  
  <p><strong>home >> service >> search-engines-and-ir</strong></p>
  
  <p>But the output is</p>
  
  <p><strong>home >> service >> content-management-systems >> search-engines-and-ir</strong></p>
  
  <p>which is obviously not correct.</p>
  
  <p>Can anybody give me a hint how to correct this issue? It would be even more elegant to avoid that depth checking, but up to now I cannot think of a other way, I am sure there is a more elegant solution.</p>
  
  <p>I work with XSLT 1.0 (libxml via PHP5).</p>
  
  <p>Hope my question is clear enough, if not, please ask :-) Thanks for the help in advance!</p>