简体   繁体   English

使用XSLT宏的Umbraco导航-无子节点的问题

[英]Umbraco Navigation using XSLT macro - issue with childless nodes

I have implemented the superfish navigation menu into an umbraco installation. 我已将superfish导航菜单实施到umbraco安装中。 Superfish simply takes a UL element and turns it into a hierarchical menu that shows child items when you hover over the parent (you remember when they were cool back in 1999 right?). Superfish只是采用了UL元素,然后将其转换为一个分层菜单,当您将鼠标悬停在父项上时会显示子项(您还记得1999年它们很酷的时候吧?)。

I cannot figure out why, on certain pages (usually ones without children), the menu does not show child items for any page. 我无法弄清楚为什么在某些页面(通常是没有孩子的页面)上,菜单没有显示任何页面的孩子项目。 My exposure to XSLT is minimal, so i must be overlooking some logic. 我对XSLT的了解很少,因此我必须忽略一些逻辑。

You can see the actual site here Hover over 'personal training' to see the menu work, now click on 'weight management' and hey-presto the magic stops happening. 您可以在此处查看实际站点。将鼠标悬停在“个人培训”上以查看菜单的工作,现在单击“体重管理”,嘿,神奇的事情停止了。

The XSLT that creates the UL structure is below, and the HTML page source tells me that its simply not generating any LI elements for child pages when the issue occurs. 下面是创建UL结构的XSLT,HTML页面源告诉我,发生问题时,它根本不会为子页面生成任何LI元素。

    <?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="html" omit-xml-declaration="yes"/>

<xsl:param name="currentPage" />

<!--This sets the level that the nav starts at and tells us if we should recurse through child elements-->
<xsl:variable name="startDepth" select="/macro/startingLevel" />
<xsl:variable name="recurse" select="/macro/recurse" />
<xsl:variable name="selectBranches" select="/macro/selectBranches"></xsl:variable>
<xsl:variable name="maxMenuDepth" select="/macro/maxMenuDepth"></xsl:variable>
<xsl:variable name="forceNode" select="/macro/forceNode"></xsl:variable>
<xsl:variable name="walkChildren" select="/macro/expandChildren"></xsl:variable>
<xsl:variable name="forceHome" select="/macro/forceHome"></xsl:variable>
<xsl:variable name="securityTrimming" select="/macro/securityTrimming"></xsl:variable>
<!--Alternate page title variable in here-->

<!--Styles for the navigation-->
<xsl:variable name="ulBaseClass" select="/macro/ulBaseClass"></xsl:variable>
<xsl:variable name="branchClass" select="/macro/branchClass"></xsl:variable>
<xsl:variable name="selectedClass" select="/macro/selectedClass"></xsl:variable>

<xsl:variable name="startLevel">
  <xsl:choose>
    <xsl:when test="$startDepth >= 0">
      <xsl:value-of select="$startDepth"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$currentPage/@level"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

  <!--This calls first iteration of the navigation, sending the first node at the correct depth found in the ancestors of the current page-->
<xsl:template match="/">
  <xsl:choose>
    <xsl:when test="$forceNode">
      <xsl:variable name="currentNode" select="umbraco.library:GetXmlNodeById($forceNode)"></xsl:variable>
      <xsl:call-template name="nodeIterator">
        <xsl:with-param name="parentNode" select="$currentNode/ancestor-or-self::*[@isDoc][@level=$startLevel]
                        [
                          string(umbracoNaviHide) != '1'
                          and ($securityTrimming != '1'
                            or umbraco.library:IsProtected(@id, @path) = false()
                            or umbraco.library:HasAccess(@id, @path) = true())
                        ]" />
        <xsl:with-param name="pseudoCurrentPage" select="$currentNode" />
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="currentNode" select="$currentPage"></xsl:variable>
      <xsl:call-template name="nodeIterator">
        <xsl:with-param name="parentNode" select="$currentNode/ancestor-or-self::*[@isDoc][@level=$startLevel]
                        [
                          string(umbracoNaviHide) != '1'
                          and ($securityTrimming != '1'
                            or umbraco.library:IsProtected(@id, @path) = false()
                            or umbraco.library:HasAccess(@id, @path) = true())
                        ]" />
        <xsl:with-param name="pseudoCurrentPage" select="$currentNode" />
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="nodeIterator">
    <xsl:param name="parentNode" />
    <xsl:param name="pseudoCurrentPage" />
    <!-- do not show info doc node types-->
  <xsl:variable name="calculatedMenuDepth" select="($parentNode/@level - $startLevel)+1" />

  <xsl:if test="$parentNode/*[@isDoc] or ($calculatedMenuDepth = 1 and $forceHome)">
    <ul>

      <xsl:attribute name="class">
        <xsl:choose>
          <xsl:when test="$calculatedMenuDepth = 1">
            <xsl:value-of select="$ulBaseClass" />
          </xsl:when>
          <!--<xsl:when test="$calculatedMenuDepth = 1">
            <xsl:value-of select="concat($ulBaseClass, ' lv', $calculatedMenuDepth)" />
          </xsl:when>
          <xsl:when test="$calculatedMenuDepth > 1">
            <xsl:value-of select="concat('lv', $calculatedMenuDepth)" />
          </xsl:when>-->
        </xsl:choose>
      </xsl:attribute>

      <xsl:if test="$forceHome = 1 and $calculatedMenuDepth = 1">
        <!-- Create the class for the li element-->
        <li>
          <xsl:variable name="isHomeSelected">
            <xsl:choose>
              <xsl:when test="$currentPage/ancestor-or-self::*[@isDoc][@level=1]/@id = $currentPage/@id">1</xsl:when>
            </xsl:choose>
          </xsl:variable>

          <xsl:call-template name="cssClassConstructor">
            <xsl:with-param name="isSelected" select="$isHomeSelected" />
            <xsl:with-param name="isSelectedBranch" select="0" />
            <xsl:with-param name="hasChildren" select="1" />
            <xsl:with-param name="selectedClass" select="$selectedClass" />
            <xsl:with-param name="branchClass" select="$branchClass" />
          </xsl:call-template>

          <a href="{umbraco.library:NiceUrl($currentPage/ancestor-or-self::*[@isDoc][@level=1]/@id)}">

            <xsl:call-template name="cssClassConstructor">
              <xsl:with-param name="isSelected" select="$isHomeSelected" />
              <xsl:with-param name="isSelectedBranch" select="0" />
              <xsl:with-param name="hasChildren" select="0" />
              <xsl:with-param name="selectedClass" select="$selectedClass" />
              <xsl:with-param name="branchClass" select="$branchClass" />
            </xsl:call-template>

            <!--set the innerText for the a element-->
            <xsl:value-of select="$currentPage/ancestor-or-self::*[@isDoc][@level=1]/text()"/>

            <xsl:if test="string($currentPage/ancestor-or-self::*[@isDoc][@level=1]/text()) = ''">
              <xsl:value-of select="$currentPage/ancestor-or-self::*[@isDoc][@level=1]/@nodeName"/>
            </xsl:if>
          </a>
        </li>
      </xsl:if>
      <!--End force home-->


      <!--for each node in the parent node that is not hidden by Umbraco-->
      <xsl:for-each select="$parentNode/*[@isDoc][
                          string(umbracoNaviHide) != '1'
                          and ($securityTrimming != '1'
                            or umbraco.library:IsProtected(@id, @path) = false()
                            or umbraco.library:HasAccess(@id, @path) = true())
                        ]">

        <!--Set the current node id i.e. the node we have looped to not the current page-->
        <xsl:variable name="currentNodeID" select="@id" />

        <!--Is the node a branch? i.e. are there children and is it in the colletion of ancestor nodes -->
        <xsl:variable name="isBranch">
          <xsl:choose>
            <xsl:when test="$currentPage/ancestor-or-self::*[@isDoc][@id = $currentNodeID]/child::*[@isDoc]">1</xsl:when>
          </xsl:choose>
        </xsl:variable>

        <!--Is the node selected? i.e. is it the same as the currentPage node-->
        <xsl:variable name="isSelected">
          <xsl:choose>
            <xsl:when test="$currentPage/@id = $currentNodeID">1</xsl:when>
            <!-- parent selected -->
            <xsl:when test="$pseudoCurrentPage/@id = $currentNodeID">1</xsl:when>

          </xsl:choose>
        </xsl:variable>

        <xsl:variable name="isSelectedBranch">
          <xsl:choose>
            <xsl:when test="$isBranch = 1 and $selectBranches = 1">1</xsl:when>
          </xsl:choose>
        </xsl:variable>

        <xsl:variable name="hasChildren">
          <xsl:choose>
            <xsl:when test="./*[@isDoc]">1</xsl:when>
          </xsl:choose>
        </xsl:variable>

        <li>

          <!-- Create the class attribute for the element-->
          <xsl:call-template name="cssClassConstructor">
            <xsl:with-param name="isSelected" select="$isSelected" />
            <xsl:with-param name="isSelectedBranch" select="$isSelectedBranch" />
            <xsl:with-param name="hasChildren" select="$hasChildren" />
            <xsl:with-param name="selectedClass" select="$selectedClass" />
            <xsl:with-param name="branchClass" select="$branchClass" />
          </xsl:call-template>

          <a href="{umbraco.library:NiceUrl(@id)}">

            <xsl:call-template name="cssClassConstructor">
              <xsl:with-param name="isSelected" select="$isSelected" />
              <xsl:with-param name="isSelectedBranch" select="$isSelectedBranch" />
              <xsl:with-param name="hasChildren" select="0" />
              <xsl:with-param name="selectedClass" select="$selectedClass" />
              <xsl:with-param name="branchClass" select="$branchClass" />
            </xsl:call-template>

            <!--set the innerText for the a element-->
            <xsl:value-of select="./pageTitle/text()"/>
            <xsl:if test="string(./pageTitle/text()) = ''">
              <xsl:value-of select="@nodeName"/>
            </xsl:if>
          </a>

          <!-- if it's a branch recurse through it's children-->
          <xsl:if test="((($isBranch = 1 and $recurse = 1) or ($walkChildren = 1 and $pseudoCurrentPage/descendant-or-self::*[@isDoc][@id = $currentNodeID]/child::*[@isDoc])) and $maxMenuDepth &gt; $calculatedMenuDepth)">
            <xsl:call-template name="nodeIterator">
              <xsl:with-param name="parentNode" select="." />
              <xsl:with-param name="pseudoCurrentPage" select="$pseudoCurrentPage" />
            </xsl:call-template>
          </xsl:if>

        </li>

      </xsl:for-each>

    </ul>
  </xsl:if>
  </xsl:template>

  <xsl:template name="cssClassConstructor">
    <xsl:param name="isSelected"></xsl:param>
    <xsl:param name="isSelectedBranch"></xsl:param>
    <xsl:param name="hasChildren"></xsl:param>
    <xsl:param name="selectedClass"></xsl:param>
    <xsl:param name="branchClass"></xsl:param>

    <xsl:variable name="class">
      <xsl:if test="$isSelected = 1">
        <xsl:value-of select="concat($selectedClass,' ')"/>
      </xsl:if>
      <xsl:if test="$isSelectedBranch = 1">
        <xsl:value-of select="concat($branchClass,' ')"/>
      </xsl:if>
      <xsl:if test="$hasChildren = 1">
        <xsl:value-of select="'hasChildren '"/>
      </xsl:if>
    </xsl:variable>

    <xsl:if test="string-length($class) > 0">
      <xsl:attribute name="class">
        <xsl:value-of select="normalize-space($class)"/>
      </xsl:attribute>
    </xsl:if>

  </xsl:template>
</xsl:stylesheet>​

The issue you describe above isn't replicating for me (I've checked your source code using Notepad++ and a diff viewer). 您上面描述的问题对我来说不是复制的(我已经使用Notepad ++和diff查看器检查了您的源代码)。 I see from your code that you're using the CogWorks' Flexible Navigation package. 我从您的代码中看到您正在使用CogWorks的Flexible Navigation软件包。 Can you ensure you're using the latest code from here ? 您能确定使用这里的最新代码吗?

Many thanks, 非常感谢,

Benjamin 本杰明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM