Reputation: 1816
I have a question on XSL-Transformation (XSLT-1). I am trying it since days, but I didn't get it to work.
I want to build a standard website tree navigation with XML and XSLT-1. It should only show the items on the path to the current item. if the current item has child-items, the next node should be opened.
My XML source is like this:
<cat>
<item id="0" name="1">
<item id="1" name="1.1"></item>
<item id="2" name="1.2"></item>
<item id="3" name="1.3"></item>
<item id="4" name="1.4">
<item id="5" name="1.4.1">
<item id="6" name="1.4.1.1"></item>
<item id="7" name="1.4.1.2"></item>
<item id="8" name="1.4.1.3"></item>
</item>
<item id="9" name="1.4.2"></item>
<item id="10" name="1.4.3"></item>
</item>
<item id="11" name="1.5"></item>
<item id="12" name="1.6"></item>
</item>
<item id="13" name="2">
<item id="14" name="2.1"></item>
<item id="15" name="2.2"></item>
</item>
<item id="16" name="3"></item>
</cat>
Now I want to call a page with an $pageid=7 send by URL, and it should show some output like this:
<ul>
<li>1
<ul>
<li>1.1</li>
<li>1.2</li>
<li>1.3</li>
<li>1.4
<ul>
<li>1.4.1
<ul>
<li>1.4.1.1</li>
<li class="activeitem">1.4.1.2</li>
<li>1.4.1.3</li>
</ul>
</li>
<li>1.4.2</li>
<li>1.4.3</li>
</ul>
</li>
<li>1.5</li>
<li>1.6</li>
</ul>
</li>
<li>2</li>
<li>3</li>
</ul>
If I call a page with an $pageid=4 send by URL, and it should show some output like this:
<ul>
<li>1
<ul>
<li>1.1</li>
<li>1.2</li>
<li>1.3</li>
<li class="activeitem">1.4
<ul>
<li>1.4.1</li>
<li>1.4.2</li>
<li>1.4.3</li>
</ul>
</li>
<li>1.5</li>
<li>1.6</li>
</ul>
</li>
<li>2</li>
<li>3</li>
</ul>
Hopefully my example is understandable for all.
I already got a sitemap and a breadcrumb navigation working, but this one seems to be very tricky and experienced.
I tried to modify the examples from Tree navigation with XML and XSLT - but it didn't worked well. It only shows the path to the item, but not the rest.
Can somebody experienced with XSLT-1 help me with it?
Or maybe somebody has already a working solution to post here?
It would be very kind. Thank you all for your attention.
Upvotes: 1
Views: 3220
Reputation: 24826
The challenge here is to find the correct test for navigating inside a new list. For a given list item, I think you are searching for this kind of test (not really obvious):
"item and .//@id=$pageid"
Check this transform out.
[XSLT 1.0]
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:param name="pageid" select="4"/>
<xsl:template match="/">
<xsl:call-template name="Navigate"/>
</xsl:template>
<xsl:template name="Navigate">
<ul>
<xsl:apply-templates select="/cat/item" mode="Navigate"/>
</ul>
</xsl:template>
<xsl:template match="item" mode="Navigate">
<li>
<xsl:apply-templates select="@id[.=$pageid]" mode="Navigate"/>
<xsl:value-of select="@name"/>
<xsl:if test="item and .//@id=$pageid">
<ul>
<xsl:apply-templates select="item" mode="Navigate"/>
</ul>
</xsl:if>
</li>
</xsl:template>
<xsl:template match="@id" mode="Navigate">
<xsl:attribute name="class">
<xsl:value-of select="'activeitem'"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
result for $pageid = 4:
<ul>
<li>1<ul>
<li>1.1</li>
<li>1.2</li>
<li>1.3</li>
<li class="activeitem">1.4<ul>
<li>1.4.1</li>
<li>1.4.2</li>
<li>1.4.3</li>
</ul>
</li>
<li>1.5</li>
<li>1.6</li>
</ul>
</li>
<li>2</li>
<li>3</li>
</ul>
result for $pageid=7:
<ul>
<li>1<ul>
<li>1.1</li>
<li>1.2</li>
<li>1.3</li>
<li>1.4<ul>
<li>1.4.1<ul>
<li>1.4.1.1</li>
<li class="activeitem">1.4.1.2</li>
<li>1.4.1.3</li>
</ul>
</li>
<li>1.4.2</li>
<li>1.4.3</li>
</ul>
</li>
<li>1.5</li>
<li>1.6</li>
</ul>
</li>
<li>2</li>
<li>3</li>
</ul>
result for $pageid=13:
<ul>
<li>1</li>
<li class="activeitem">2<ul>
<li>2.1</li>
<li>2.2</li>
</ul>
</li>
<li>3</li>
</ul>
Upvotes: 2
Reputation: 70618
I think the logic is that if an item has the selected page as a descendent, or is the selected page, then you want to see all child items of for that item.
Here is my attempt...
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="pageNum" select="13" />
<xsl:template match="/cat">
<ul>
<xsl:apply-templates />
</ul>
</xsl:template>
<xsl:template match="item">
<li>
<xsl:if test="@id=$pageNum">
<xsl:attribute name="class">activeitem</xsl:attribute>
</xsl:if>
<xsl:value-of select="@name" />
<xsl:choose>
<xsl:when test="descendant-or-self::item[@id=$pageNum] and count(node()) > 0">
<ul>
<xsl:apply-templates />
</ul>
</xsl:when>
</xsl:choose>
</li>
</xsl:template>
</xsl:stylesheet>
For 4 and 7 the expected output is as shown in the question. For 13, the output is as follows:
<ul>
<li>1</li>
<li class="activeitem">2
<ul>
<li>2.1</li>
<li>2.2</li>
</ul>
</li>
<li>3</li>
</ul>
Upvotes: 1