Developer forum

Forum » Templates » XSLT navigation - parents, descendants, siblings

XSLT navigation - parents, descendants, siblings

Bogdan Ciocsan
Reply

Hi guys. I am relatively new to XSLT, and I am trying to create a navigation that shows the next article in a menu (should traverse all items).

I have the following site structure: 

Blog

-- Video 01

   -- Video 02

   -- Video 03

-- Article 01

   -- Article 02

      -- Article 03

   -- Article 04

-- Another page 

-- Last page

The link that I get should traverse all items downwards, and if it reaches the end it should go up to its parent and show the following-sibling. I found it easy to navigate downwards, I did by checking if there are any descendants, and then show next descendant in line. 

My problem is that I don't know how to check for the parents sibling recursively (regardless of how many levels up it should go). 

I tried the following for each: 

<xsl:for-each select="Page[@ID = //GlobalTags/Global.Page.ID]/ancestor::*/following-sibling::Page[1]"> 
   <xsl:value-of select="@FriendlyHref"/> 
</xsl:for-each>

But this will output all following-siblings, and I just need the @FriendlyHref from the next sibling. I tried creating a variable to stop the loop after the first run, but it didn't work.

Does anyone know what I am doing wrong?

Thanks a lot in advance.


Replies

 
Nuno Aguiar
Reply
This post has been marked as an answer

Hi Bogdan,

 

Can you send me the entire xslt file? I can try and help you out but need a little more context.

 

But the looks of it should be OK, but if you only want 1, you could convert those 3 lines into

<xsl:value-of select:"Page[@ID = //GlobalTags/Global.Page.ID]/ancestor::*/following-sibling::Page[1]/@FriendlyHref" />

 

Best Regards,

Nuno

Votes for this answer: 1
 
Bogdan Ciocsan
Reply

Hi Nuno,

I edited my code, and it seems that your suggestion has fixed my problem regarding ancestors/parents. Thanks a lot for the help!

I have some problems with it showing the next page, when it has no ancestors.

EDIT: It works fine, the first time I navigate through all items, but the second time it will give me a wrong link. I guess it's because it is not recursive.

Here is my full xslt: 

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="html" omit-xml-declaration="yes" indent="yes"  encoding="utf-8" />
  <xsl:variable name="PageID" select="//GlobalTags/Global.Page.ID" />

  <xsl:template match="/NavigationTree">
    <xsl:apply-templates select="//Page" />
  </xsl:template>

  <xsl:template match="Page">
    <xsl:choose>
      <xsl:when test="Page[@ID = $PageID]/descendant::*">
        <xsl:value-of select="Page[@ID = $PageID]/descendant::Page[1]/@FriendlyHref"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:choose>
          <xsl:when test="Page[@ID = $PageID]/ancestor::*">
            <xsl:value-of select="Page[@ID = $PageID]/ancestor::*/following-sibling::Page[1]/@FriendlyHref"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="self::node()[@ID = $PageID]/following-sibling::Page[1]/@FriendlyHref"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
 
Bogdan Ciocsan
Reply

After a bit of reflecting over my code I managed to fix the problem and now it works, regardless of how many levels I have on my navigation. Thanks a lot Nuno :) I marked your reply as an answer because it helped me figure out what was wrong in my logic.

The final code ended up looking as: 

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="html" omit-xml-declaration="yes" indent="yes"  encoding="utf-8" />
  <xsl:variable name="PageID" select="//GlobalTags/Global.Page.ID" />

  <xsl:template match="/NavigationTree">
    <xsl:apply-templates select="//Page[@ID = $PageID]" />
  </xsl:template>

  <xsl:template match="Page">
    <xsl:choose>
      <xsl:when test="descendant::*">
        <xsl:value-of select="descendant::Page[1]/@FriendlyHref"/>
      </xsl:when>
      <xsl:when test="following-sibling::*">
        <xsl:value-of select="following-sibling::Page[1]/@FriendlyHref"/>
      </xsl:when>
      <xsl:when test="ancestor::*">
        <xsl:value-of select="ancestor::*/following-sibling::Page[1]/@FriendlyHref"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="self::node()/following-sibling::Page[1]/@FriendlyHref"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
 
Nicolai Høeg Pedersen
Reply

Great - glad you got it working.

Thank you for sharing!

 
Nuno Aguiar
Reply

Hi Bogdan,

 

Good to know.

 

FYI: You can always use "." instead of "self::node()"

 

Best Regards,

Nuno

 
Bogdan Ciocsan
Reply

Hi Nuno.

Thanks, I will do :) 

Best regards,

Bogdan 

 

You must be logged in to post in the forum