Copied to clipboard

Flag this post as spam?

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


  • Paul M. 4 posts 24 karma points
    Aug 25, 2011 @ 23:25
    Paul M.
    0

    Newb, have mercy, XSLT is driving me mad

    I'm spec'ing out an ecommerce site for an important group using the wicked combination of Umbraco and TeaCommerce, but I've hit a snag that I just can't figure out.  I've enabled nesting a Product Category within another Product Category (a.k.a. Sub-Category, doesn't everyone need them?), but it breaks the Navigation.xslt from the StarterKit.

    Here's the result of the page load, note that everything below the first <li> doesn't get it's class populated almost as if the XSLT is "stopping" after the first <li>:

    <ul id="submenu" class="lvl1">
    <li class="active inpath firstitem hasChildren">
    <a title="Comics &amp; Humor" class="active inpath firstitem hasChildren" href="/en/products/comics-humor.aspx">Comics &amp; Humor</a>
    <ul class="lvl2"><li class="firstitem lastitem hasChildren">
    <a title="New Releases" class="firstitem lastitem hasChildren" href="/en/products/comics-humor/new-releases.aspx">New Releases</a></li></ul></li>
    <li><a title="Puzzles &amp; Games" href="/en/products/puzzles-games.aspx">Puzzles &amp; Games</a></li>
    <li><a title="Cookbooks" href="/en/products/cookbooks.aspx">Cookbooks</a></li>
    <li><a title="Home &amp; Crafts" href="/en/products/home-crafts.aspx">Home &amp; Crafts</a></li>
    <li><a title="Non-fiction" href="/en/products/non-fiction.aspx">Non-fiction</a></li>
    <li><a title="Keepsake &amp; Gift" href="/en/products/keepsake-gift.aspx">Keepsake &amp; Gift</a></li>
    <li><a title="Children's" href="/en/products/children's.aspx">Children's</a></li>
    <li class="lastitem"><a title="Calendars" class="lastitem" href="/en/products/calendars.aspx">Calendars</a></li></ul>

     

    Here's the unmodified XSLT (every change I made failed to fix the problem):

     

    <?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" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets"
      exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">

    <xsl:output method="xml" omit-xml-declaration="yes"/>
    <xsl:param name="currentPage"/>
    <!-- GLOBAL VARIABLES START -->
    <xsl:variable name="Navigation.rootNodeId">
      <xsl:choose>
        <xsl:when test="/macro/rootPage != ''">
        <xsl:value-of select="/macro/rootPage" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$currentPage/@id" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="Navigation.rootNode" select="umbraco.library:GetXmlNodeById($Navigation.rootNodeId)"/>
        
    <xsl:variable name="Navigation.fromLevel">
      <xsl:choose>
        <xsl:when test="string(/macro/useSelfAsRoot) = '1'">
          <xsl:value-of select="number($Navigation.rootNode/@level) + 1" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:choose>
            <xsl:when test="/macro/fromLevel != ''">
              <xsl:value-of select="/macro/fromLevel" />
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="2" />
            </xsl:otherwise>
          </xsl:choose>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="Navigation.toLevel">
      <xsl:choose>
        <xsl:when test="/macro/numberOfLevels != ''">
          <xsl:value-of select="number($Navigation.fromLevel) + number(/macro/numberOfLevels) - 1" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="1000" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
        
    <xsl:variable name="Navigation.showOnlyCurrentPath">
      <xsl:choose>
        <xsl:when test="/macro/showOnlyCurrentPath != ''">
          <xsl:value-of select="/macro/showOnlyCurrentPath" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="0" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
        
    <xsl:variable name="Navigation.isSitemap">
      <xsl:choose>
        <xsl:when test="/macro/isSitemap != ''">
          <xsl:value-of select="/macro/isSitemap " />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="0" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <!-- GLOBAL VARIABLES END -->
    <xsl:template match="/">
      
      <xsl:call-template name="MenuItems">
        <xsl:with-param name="menuItems" select="$Navigation.rootNode/ancestor-or-self::* [@level=number($Navigation.fromLevel - 1)]/* [@isDoc and ( ( $Navigation.isSitemap != '1' and string(./umbracoNaviHide) = '0' ) or ( $Navigation.isSitemap = '1' and string(./umbracoSitemapHide) = '0' ) )]" />
        <xsl:with-param name="currentLevel" select="$Navigation.fromLevel" />
        <xsl:with-param name="levelCounter" select="1" />
      </xsl:call-template>
    </xsl:template>
        
    <xsl:template name="MenuItems">
      <!-- VARIABLES START -->
      <xsl:param name="menuItems"/>
      <xsl:param name="currentLevel"/>
      <xsl:param name="levelCounter"/>
      
      <xsl:variable name="count" select="count($menuItems)"/>
      <!-- VARIABLES END -->
      
      <!-- HTML START -->
      <xsl:if test="$count &gt; 0">
        <ul>
          <xsl:if test="$levelCounter = 1 and /macro/navigationId">
            <xsl:attribute name="id"><xsl:value-of select="/macro/navigationId"/></xsl:attribute>
          </xsl:if>
          <xsl:attribute name="class"><xsl:value-of select="concat('lvl', $levelCounter)"/></xsl:attribute>
          
          <xsl:for-each select="$menuItems">
            <xsl:sort select="@sortOrder" order="ascending" data-type="number"/>
            
            <xsl:if test="umbraco.library:IsProtected(@id, @path) = 0 or (umbraco.library:IsProtected(@id, @path) = 1 and umbraco.library:IsLoggedOn() = 1)">
              
              <xsl:variable name="childMenuItems" select="./* [@isDoc and ( ( $Navigation.isSitemap != '1' and string(./umbracoNaviHide) = '0' ) or ( $Navigation.isSitemap = '1' and string(./umbracoSitemapHide) = '0' ) )]"/>
              <xsl:variable name="active" select="$currentPage [@isDoc]/@id=@id"/>
              <xsl:variable name="inpath" select="$currentPage/ancestor-or-self::* [@isDoc]/@id=@id"/>
              <xsl:variable name="firstitem" select="position() = 1"/>
              <xsl:variable name="lastitem" select="position() = $count"/>
              <xsl:variable name="hasChildren" select="count($childMenuItems) &gt; 0"/>
              <xsl:variable name="className">
                <xsl:if test="$active = '1' or $inpath = '1' or $firstitem = '1' or $lastitem = '1' or $hasChildren = '1'">
                  <xsl:if test="$active = '1'">active</xsl:if>
                  <xsl:if test="$inpath = '1' and $active = '1'"><xsl:text> </xsl:text></xsl:if>
                  <xsl:if test="$inpath = '1'">inpath</xsl:if>
                  <xsl:if test="$inpath = '1' and ($firstitem = '1' or $lastitem = '1')"><xsl:text> </xsl:text></xsl:if>
                  <xsl:if test="$firstitem = '1'">firstitem</xsl:if>
                  <xsl:if test="$firstitem = '1' and $lastitem = '1'"><xsl:text> </xsl:text></xsl:if>
                  <xsl:if test="$lastitem = '1'">lastitem</xsl:if>
                  <xsl:if test="($inpath = '1' or $firstitem = '1' or $lastitem = '1') and $hasChildren = '1'"><xsl:text> </xsl:text></xsl:if>
                  <xsl:if test="$hasChildren = '1'"><xsl:text>hasChildren</xsl:text></xsl:if>
                </xsl:if>
              </xsl:variable>
              
              <li>
                <xsl:if test="$className != ''"><xsl:attribute name="class"><xsl:value-of select="$className" /></xsl:attribute></xsl:if>
                
                <a title="{@nodeName}">
                  <xsl:if test="$className != ''"><xsl:attribute name="class"><xsl:value-of select="$className" /></xsl:attribute></xsl:if>
                  <xsl:attribute name="href">
                    <xsl:choose>
                      <xsl:when test="local-name() != 'ExternalLink'">
                        <xsl:value-of select="umbraco.library:NiceUrl(@id)" />
                      </xsl:when>
                      <xsl:otherwise>
                        <xsl:value-of select="./externalURL" />
                      </xsl:otherwise>
                    </xsl:choose>
                  </xsl:attribute>
                  
                  <xsl:value-of select="@nodeName" />
                </a>
                <xsl:if test=" number($currentLevel) &lt; number($Navigation.toLevel) and ( ( $inpath = '1' and string($Navigation.showOnlyCurrentPath) != '0' ) or string($Navigation.showOnlyCurrentPath) = '0' )">
                  <xsl:call-template name="MenuItems">
                    <xsl:with-param name="menuItems" select="$childMenuItems" />
                    <xsl:with-param name="currentLevel" select="$currentLevel+1" />
                    <xsl:with-param name="levelCounter" select="$levelCounter+1" />
                  </xsl:call-template>
                </xsl:if>
              </li>
            </xsl:if>
          </xsl:for-each>
          
        </ul>
      </xsl:if>
      <!-- HTML END -->
    </xsl:template>
    </xsl:stylesheet>

     

    Here's a look at my content tree, there are additional subcategories and products populated for the subcategories that are just not showing up.

    Any suggestions, other than "learn more about XSLT"? :)

  • Anders Burla 2560 posts 8256 karma points
    Aug 25, 2011 @ 23:30
    Anders Burla
    0

    Hi Paul

    XSLT is a little hard to start with - but you will learn it :)

    What is the toLevel and numberOfLevels in the Macro parameters?

  • Paul M. 4 posts 24 karma points
    Aug 25, 2011 @ 23:34
    Paul M.
    0

    Thanks, it's on my list :)

    fromLevel is 4 and numberofLevels is 2, just the OOB stuff

    <umbraco:Macro fromLevel="4" navigationId="submenu" numberOfLevels="2" rootPage="" showOnlyCurrentPath="0" useSelfAsRoot="0" isSitemap="0" Alias="Navigation" runat="server">umbraco:Macro>
  • Anders Burla 2560 posts 8256 karma points
    Aug 25, 2011 @ 23:39
    Anders Burla
    0

    How did you publish the subcategories? Bulk publish? Try publish one by it self.

  • Paul M. 4 posts 24 karma points
    Aug 25, 2011 @ 23:42
    Paul M.
    0

    Bulk...was that a bad idea?

  • Anders Burla 2560 posts 8256 karma points
    Aug 25, 2011 @ 23:48
    Anders Burla
    0

    No not at all - but for some reason the umbraco xml isnt updated correctly so it only shows up in the navigation when you publish each sub category by it self. Try it. :)

  • Rune Grønkjær 1372 posts 3103 karma points
    Aug 26, 2011 @ 08:15
    Rune Grønkjær
    0

    Hi Paul,

    Your problem seems to be that the "showOnlyCurrentPath" parameter is set to "1". You can see that in the template where you have the macro inserted. That parrameter sees to that the navigation.xslt only shows subpages of the active item. In your example above the "The Comics and humor" node is "active" and "inpath". If  "showOnlyCurrentPath" is set to "0" all levels will be opened.

    Maybe I should write a little blogpost on our navigation.xslt one of these days! It's pretty neat, if you know how to use it ;)

    /Rune

  • Paul M. 4 posts 24 karma points
    Aug 26, 2011 @ 15:39
    Paul M.
    0

    Wow, you guys rock, thanks for the awesome and quick support.  

    Here's what I had to do to get sub-categories to display in the submenu:

    1. Unpublish each subcategory and product within
    2. Manually publish each subcategory and product within individually

    Rune, I did have showOnlyCurrentPath set to 0 so I could make sure to see all categories while testing and if I set it to 1 everything seems to still work ok.  I would imagine if I opened it up to another level (i.e. Products, which I won't because there will be a ton) it would likely have issues though.  

    Just having a starting point (i.e. the Navigation.xslt in the starter kit) is an incredible thing, much appreciated.  A blog post or wiki explaining it's usage would be beneficial, but it's very well laid out and even just a few comment lines within the XSLT might be just as effective.  I may do just that and if I do I'll post the modified file.

    Big thanks once again Anders and Rune,

    Paul

Please Sign in or register to post replies

Write your reply to:

Draft