3 users online. Create an account or sign in to join them.Users
Dynamic subnavigation-utility
This is an open discussion with 4 replies, filed under XSLT.
Search
So, the root of your problem is that $match-path is a string because you're using concat(), which outputs a string. You can't use a string as an xpath query. I have run into the problem of dynamically generating an xpath query before, and there is no simple solution. You might be able to concat your 'navigation-???' element into a string, then use that directly in the XPath. If that doesn't work, you could possibly test for the name of that element.
so something like this <xsl:with-param name="match-path" select="/data/$navigation-name/entry"/>
or this <xsl:with-param name="match-path" select="/data/*[name()='$navigation-name']/entry"/>
not sure about the name() function, but I think that's right
I was thinking about doing something similar. The trick is to make sure that the XPath expression can be properly evaluated as a node-set. As soon as you turn the expression into a string, it can no longer be evaluated as a node-set and you'll get a "wrong type" error.
So, ashooner was on the right track, but I think some of the details were a little off. A parameter cannot be used as part of the XPath expression:
/data/$navigation-name/entry
And the name() function is trying to match a string, rather than a parameter, because of the single quotes, and I think the name() function needs a specific node to return the element name:
name()='$navigation-name'
Try something like this:
<xsl:param name="navigation-entries" select="/data/*[name(.) = concat('navigation",'-',$navigation-name)]/entry"/>
Then you have a valid XPath expression that you can use with the xsl:for-each instruction:
<xsl:for-each select="$navigation-entries"> <xsl:value-of select="blah"/> </xsl:for-each>
Thanks a bunch, guys!
Bauhouse, you were right. The funny part is, that I have to put this whole /data/*[...]/entry-thing into the subnavigation-template. It does not work in the match="page"-part.
This is the whole working XSLT-Template
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="navigation">
<xsl:apply-templates select="page[not(types/type = 'hidden') and not(types/type = 'admin')]"/>
<xsl:if test="/data/events/login-info/@logged-in = 'true'">
<li><a href="{$root}/drafts/">Drafts</a></li>
<li><a href="{$root}/symphony/">Admin</a></li>
<li><a href="?debug">Debug</a></li>
</xsl:if>
</xsl:template>
<xsl:template match="page">
<ul id="nav-{@handle}">
<li class="rubrik">
<xsl:if test="@handle = $current-page">
<xsl:attribute name="id">subactive</xsl:attribute>
</xsl:if>
<a href="{$root}/{@handle}/" class="rubrik">
<xsl:value-of select="name"/>
</a>
<xsl:call-template name="subnavigation">
<xsl:with-param name="match-name" select="@handle"/>
</xsl:call-template>
</li>
</ul>
</xsl:template>
<xsl:template name="subnavigation">
<xsl:param name="match-path" select="/data/*[name(.) = concat('navigation-',$match-name)]/entry" />
<xsl:if test="count($match-path) != 0">
<ul>
<xsl:for-each select="$match-path">
<li>
<!-- $content-handle is the URL Parameter -->
<xsl:if test="$content-handle = titel/@handle">
<xsl:attribute name="class">active</xsl:attribute>
</xsl:if>
<a href="{$root}/{$match-name}/{titel/@handle}/">
<xsl:value-of select="titel"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
It looks like I had errors of my own. I see you fixed up the syntax I suggested for the concat function. Glad that's working for you.
Create an account or sign in to comment.
I'm trying to build an efficient navigation-utility with two navigation levels. I have 4 pages (first-level navigation) and 4 sections (each contains entries which are the second-level).
My problem: The
<xsl:with-param>-part does not work. It outputs the right path, but thefor-eachdoes not work. When I enter the correct path directly in thefor-eachinstead of using theparam, it does work.Any idea how to fix this? Or is it not possible to create a dynamic
for-each?snippet from my XML:
<navigation> <page handle="startseite"> <name>Startseite</name> <types> <type>hidden</type> </types> </page> <page handle="profil"> <name>Profil</name> </page> <page handle="projekte"> <name>Projekte</name> </page> <page handle="lehre"> <name>Lehre</name> </page> <page handle="kontakt"> <name>Kontakt</name> </page> </navigation> <navigation-profil> <section id="13" handle="profil">Profil</section> <entry id="117"> <titel handle="promotion">Promotion</titel> </entry> <entry id="118"> <titel handle="lehre">Lehre</titel> </entry> <entry id="119"> <titel handle="kommunikation">Kommunikation</titel> </entry> </navigation-profil> <navigation-projekte> ... </navigation-projekte> ...snippet from my XSLT
<xsl:template match="page"> <li class="rubrik"> <a href="{$root}/{@handle}/" class="rubrik"> <xsl:value-of select="name"/> </a> <xsl:call-template name="subnavigation"> <xsl:with-param name="match-path" select="concat('/data/navigation-', @handle, '/entry')"/> </xsl:call-template> </li> </xsl:template> <xsl:template name="subnavigation"> <ul> <xsl:for-each select="$match-path"> <li> <a href="{$root}/{titel/@handle}/"> <xsl:value-of select="titel"/> </a> <xsl:if test="@handle = $current-page"> <xsl:attribute name="class">active</xsl:attribute> </xsl:if> </li> </xsl:for-each> </ul> </xsl:template>