Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • syn-rg 282 posts 425 karma points
    Sep 18, 2012 @ 07:21
    syn-rg
    0

    Creating vertical multilevel navigation for umbraco XSLT

    I'm trying to create a vertical multilevel nav for Umbraco using XSLT, that will add nested lists automatically. Currently I have had to keep adding each nested list manually into the XSLT (which is not good practice).

    I've created the following menu but I need help as it's not creating the nest lists properly:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
    <xsl:stylesheet
     
    version="1.0"
     
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     
    xmlns:msxml="urn:schemas-microsoft-com:xslt"
     
    xmlns:umbraco.library="urn:umbraco.library"
     
    exclude-result-prefixes="msxml umbraco.library">

    <xsl:output method="xml" omit-xml-declaration="yes"/>

    <xsl:param name="currentPage"/>

    <xsl:template match="/">
    <xsl:variable name="level1" select="$currentPage/ancestor-or-self::* [@level = 2 and string(umbracoNaviHide) != '1' and string(hideFromSideNavigation) != '1']" />  
    <xsl:variable name="level" select="2"/>

    <div class="subnav">
       
    <!-- LEVEL 1 -->
       
    <p><xsl:value-of select="$level1/@nodeName"/></p>

       
    <ul>
           
    <xsl:call-template name="drawNodes">
               
    <xsl:with-param name="parent" select="$currentPage/ancestor-or-self::* [@isDoc][@level=2]"/>
           
    </xsl:call-template>
       
    </ul>
    </div>
    </xsl:template>

    <xsl:template name="drawNodes">
       
    <xsl:param name="parent"/>
       
    <xsl:for-each select="$parent/ancestor-or-self::* [@level=2]/* [@isDoc and string(umbracoNaviHide) != '1' and string(@template) != '0']">
           
    <li>
               
    <xsl:if test="descendant-or-self::*[@id = $currentPage/@id]">
                   
    <xsl:attribute name="class">current</xsl:attribute>
               
    </xsl:if>

               
    <xsl:if test="count(./* [@isDoc and string(umbracoNaviHide) != '1' and string(@template) != '0']) = 0">
                   
    <a href="{umbraco.library:NiceUrl(@id)}">
                       
    <xsl:value-of select="@nodeName"/>
                   
    </a>
               
    </xsl:if>

               
    <xsl:if test="count(./* [@isDoc and string(umbracoNaviHide) != '1' and string(@template) != '0']) > 0">
                   
    <a href="{umbraco.library:NiceUrl(@id)}">
                       
    <xsl:value-of select="@nodeName"/>
                   
    </a>
                   
    <ul>
                       
    <xsl:choose>
                           
    <xsl:when test="./umbracoNaviHide != '1'">
                               
    <li>
                                   
    <xsl:if test="descendant-or-self::*[@id = $currentPage/@id]">
                                       
    <xsl:attribute name="class">current</xsl:attribute>
                                   
    </xsl:if>
                                   
    <a href="{umbraco.library:NiceUrl(@id)}">
                                       
    <xsl:value-of select="@nodeName"/>
                                   
    </a>
                               
    </li>
                           
    </xsl:when>
                       
    </xsl:choose>
                       
    <xsl:call-template name="drawNodes">
                           
    <xsl:with-param name="parent" select="."/>
                       
    </xsl:call-template>
                   
    </ul>
               
    </xsl:if>
           
    </li>
       
    </xsl:for-each>
    </xsl:template>

    </xsl:stylesheet>

    Here's manual added nested lists XSLT:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
    <xsl:stylesheet
     
    version="1.0"
     
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     
    xmlns:msxml="urn:schemas-microsoft-com:xslt"
     
    xmlns:umbraco.library="urn:umbraco.library"
     
    exclude-result-prefixes="msxml umbraco.library">

    <xsl:output method="xml" omit-xml-declaration="yes"/>

    <xsl:param name="currentPage"/>

    <xsl:template match="/">
    <xsl:variable name="level1" select="$currentPage/ancestor-or-self::* [@level = 2 and string(umbracoNaviHide) != '1' and string(hideFromSideNavigation) != '1']" />  
    <xsl:variable name="level" select="2"/>

    <div class="subnav">
       
    <!-- LEVEL 1 -->
       
    <p><xsl:value-of select="$level1/@nodeName"/></p>
       
    <!-- LEVEL 2 -->
       
    <ul>
           
    <xsl:for-each select="$currentPage/ancestor-or-self::* [@level=$level]/* [@isDoc and string(umbracoNaviHide) != '1' and string(@template) != '0']">
               
    <li>
                   
    <xsl:if test="descendant-or-self::*[@id = $currentPage/@id]">
                       
    <xsl:attribute name="class">current</xsl:attribute>
                   
    </xsl:if>
                   
    <a href="{umbraco.library:NiceUrl(@id)}">
                       
    <xsl:value-of select="@nodeName"/>
                   
    </a>
                   
    <!-- LEVEL 3 if any more nodes are Visible -->
                   
    <xsl:if test="*[@isDoc][not(umbracoNaviHide = 1)]">
                       
    <ul>
                           
    <xsl:for-each select="./* [@isDoc and string(umbracoNaviHide) != '1' and string(@template) != '0']">
                               
    <li>
                                   
    <xsl:if test="descendant-or-self::*[@id = $currentPage/@id]">
                                       
    <xsl:attribute name="class">current</xsl:attribute>
                                   
    </xsl:if>
                                   
    <a href="{umbraco.library:NiceUrl(@id)}">
                                       
    <xsl:value-of select="@nodeName"/>
                                   
    </a>
                                   
    <!-- LEVEL 4 if any more nodes are Visible -->
                                   
    <xsl:if test="*[@isDoc][not(umbracoNaviHide = 1)]">
                                       
    <ul>
                                           
    <xsl:for-each select="./* [@isDoc and string(umbracoNaviHide) != '1' and string(@template) != '0']">
                                               
    <li>
                                                   
    <xsl:if test="descendant-or-self::*[@id = $currentPage/@id]">
                                                       
    <xsl:attribute name="class">current</xsl:attribute>
                                                   
    </xsl:if>
                                                   
    <a href="{umbraco.library:NiceUrl(@id)}">
                                                       
    <xsl:value-of select="@nodeName"/>
                                                   
    </a>
                                                   
    <!-- LEVEL 5 if any more nodes are Visible -->
                                                   
    <xsl:if test="*[@isDoc][not(umbracoNaviHide = 1)]">
                                                       
    <ul>
                                                           
    <xsl:for-each select="./* [@isDoc and string(umbracoNaviHide) != '1' and string(@template) != '0']">
                                                               
    <li>
                                                                   
    <xsl:if test="descendant-or-self::*[@id = $currentPage/@id]">
                                                                       
    <xsl:attribute name="class">current</xsl:attribute>
                                                                   
    </xsl:if>
                                                                   
    <a href="{umbraco.library:NiceUrl(@id)}">
                                                                       
    <xsl:value-of select="@nodeName"/>
                                                                   
    </a>
                                                               
    </li>
                                                           
    </xsl:for-each>
                                                       
    </ul>
                                                   
    </xsl:if>
                                               
    </li>
                                           
    </xsl:for-each>
                                       
    </ul>
                                   
    </xsl:if>
                               
    </li>
                           
    </xsl:for-each>
                       
    </ul>
                   
    </xsl:if>
               
    </li>
           
    </xsl:for-each>
       
    </ul>
    </div>
    </xsl:template>

    </xsl:stylesheet>

    Can anyone suggest a solution?

  • Chriztian Steinmeier 2726 posts 8320 karma points MVP 4x admin c-trib
    Sep 18, 2012 @ 08:37
    Chriztian Steinmeier
    1

    Hi JV,

    This is one of the things XSLT's templates are awesome at - here's a very simple infinite levels navigation for you to build upon:

    <?xml version="1.0" encoding="utf-8" ?>
    <xsl:stylesheet
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:umb="urn:umbraco.library"
        exclude-result-prefixes="umb"
    >
    
        <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    
        <xsl:param name="currentPage" />
        <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />
    
        <xsl:template match="/">
            <ul id="nav">
                <xsl:apply-templates select="$siteRoot/*[@isDoc][not(umbracoNaviHide = 1)]" />
            </ul>
        </xsl:template>
    
        <!-- Generic template for the links -->
        <xsl:template match="*[@isDoc]">
            <!-- Grab the child nodes here (if any) -->
            <xsl:variable name="childNodes" select="*[@isDoc][not(umbracoNaviHide = 1)]" />
            <li>
                <!-- Add class if any visible children -->
                <xsl:if test="$childNodes"><xsl:attribute name="class">selected</xsl:attribute></xsl:if>
                <a href="{umb:NiceUrl(@id)}" title="{@nodeName}">
                    <xsl:value-of select="@nodeName" />
                </a>
    
                <xsl:if test="$childNodes">
                    <ul>
                        <xsl:apply-templates select="$childNodes" />
                    </ul>
                </xsl:if>
            </li>
        </xsl:template>
    
    </xsl:stylesheet>

    /Chriztian

  • syn-rg 282 posts 425 karma points
    Sep 18, 2012 @ 09:34
    syn-rg
    0

    Thanks Chriztian,

    I've made some edits, but I need to add a "current" CSS class. I tried using the following but it doesn't work:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
    <xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxml="urn:schemas-microsoft-com:xslt"
    xmlns:umbraco.library="urn:umbraco.library"
    exclude-result-prefixes="msxml umbraco.library">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />

    <xsl:param name="currentPage" />
    <xsl:variable name="level1" select="$currentPage/ancestor-or-self::* [@level = 2 and string(umbracoNaviHide) != '1' and string(hideFromSideNavigation) != '1']" />
    <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 2]" />

    <xsl:template match="/">
    <div class="subnav">
    <!-- LEVEL 1 -->
    <p><xsl:value-of select="$level1/@nodeName"/></p>
    <!-- LEVEL 2 -->
    <ul>
    <xsl:apply-templates select="$siteRoot/*[@isDoc][not(umbracoNaviHide = 1)]" />
    </ul>
    </div>
    </xsl:template>
    <!-- Generic template for the links -->
    <xsl:template match="*[@isDoc]">
    <!-- Grab the child nodes here (if any) -->
    <xsl:variable name="childNodes" select="*[@isDoc][not(umbracoNaviHide = 1)]" />
    <li>
    <!-- Add class to current selection and any descendants -->
    <xsl:if test="descendant-or-self::*[@id = $currentPage/@id]">
    <xsl:attribute name="class">current</xsl:attribute>
    </xsl:if>
    <!-- Add class if any visible children -->
    <xsl:if test="$childNodes">
    <xsl:attribute name="class">folder</xsl:attribute>
    </xsl:if>
    <a href="{umbraco.library:NiceUrl(@id)}">
    <xsl:value-of select="@nodeName"/>
    </a>
    <xsl:if test="$childNodes">
    <ul>
    <xsl:apply-templates select="$childNodes" />
    </ul>
    </xsl:if>
    </li>
    </xsl:template>

    </xsl:stylesheet>
  • Ismail Mayat 4511 posts 10059 karma points MVP 2x admin c-trib
    Sep 18, 2012 @ 11:34
    Ismail Mayat
    1

    jv,

    take a log at my colleguaes package called flexible navigation there is xslt and razor versions http://our.umbraco.org/projects/website-utilities/cogworks-flexible-navigation

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies