使用 xslt 为 Umbraco 创建菜单

发布于 2024-08-30 05:09:46 字数 7705 浏览 3 评论 0 原文

我使用 XSLT 在 umbraco 中创建了一个菜单。菜单使用通常的 ul 和 li 元素,我仅显示菜单的第一级。目的是创建一个菜单,当我单击父节点(在顶层)时,该菜单会展开以显示子菜单。

我在 xslt 之后,单击时需要公开子菜单。

我想我需要利用祖先或自我来检测当前菜单和父菜单并显示它们以及 $currentPage 变量。

我有以下 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" 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" xmlns:tagsLib="urn:tagsLib" xmlns:urlLib="urn:urlLib" 
    exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets tagsLib urlLib ">

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

<xsl:param name="currentPage"/>

<xsl:template match="/">
    <div id="kb-categories"> 
        <h3>Categories</h3>
        <xsl:call-template name="drawNodes">  
            <xsl:with-param name="parent" select="$currentPage/ancestor-or-self::node [@level=1]"/>  
        </xsl:call-template>
    </div>
</xsl:template>

<xsl:template name="drawNodes">
    <xsl:param name="parent"/> 
    <xsl:if test="(umbraco.library:IsProtected($parent/@id, $parent/@path) = 0 or (umbraco.library:IsProtected($parent/@id, $parent/@path) = 1)) and $parent/@level = 1">           
        <ul class="kb-menuLevel1" >     
        <xsl:for-each select="$parent/node [string(./data [@alias='showInMenu']) = 1]"> 
            <li>  
                <a href="/kb{umbraco.library:NiceUrl(@id)}">
                    <xsl:value-of select="@nodeName"/>
                </a>                
                <xsl:variable name="level" select="@level" />
                <xsl:if test="(count(./node [string(./data [@alias='showInMenu']) = '1']) &gt; 0)">   
                    <xsl:call-template name="drawNodes">    
                        <xsl:with-param name="parent" select="."/>    
                    </xsl:call-template>  
                </xsl:if> 
            </li> 
        </xsl:for-each>
        </ul>
    </xsl:if>
    <xsl:if test="(umbraco.library:IsProtected($parent/@id, $parent/@path) = 0 or (umbraco.library:IsProtected($parent/@id, $parent/@path) = 1)) and $parent/@level &gt; 1">    
        <ul class="kb-menuLevel{@level}" style="display: none;">            
        <xsl:for-each select="$parent/node [string(./data [@alias='showInMenu']) = 1]"> 
            <li>  
                <a href="/kb{umbraco.library:NiceUrl(@id)}">
                    <xsl:value-of select="@nodeName"/>
                </a>                
                <xsl:variable name="level" select="@level" />
                <xsl:if test="(count(./node [string(./data [@alias='showInMenu']) = '1']) &gt; 0)">   
                    <xsl:call-template name="drawNodes">    
                        <xsl:with-param name="parent" select="."/>    
                    </xsl:call-template>  
                </xsl:if> 
            </li>
        </xsl:for-each>
        </ul>
    </xsl:if>

</xsl:template>

</xsl:stylesheet>

我怀疑这可以使用 apply-templates 进行改进,但我还没有跟上它的速度(这只是我学习 xslt 的第二天)。

我的菜单:

  • 菜单项 1
  • 菜单项 2
  • 菜单项 3
  • 菜单项 4

当我单击菜单项 2 时,我将进入菜单项 2 的页面,并且还会显示子菜单:

  • 菜单项 1
  • 菜单项 2
    -- 菜单项 2.1
    -- 菜单项 2.2
  • 菜单项 3
  • 菜单项 4

等等在嵌套菜单中。

以下是上述内容的一些示例 xml。

<root>  
    <node id="1" nodeTypeAlias="kbHomepage" nodeName="Home" level="1">
        <data alias="introduction">
            <![CDATA[<p>Welcome</p>]]>
        </data>
        <node id="2" nodeTypeAlias="guide" nodeName="Menu Item 1" level="2">
            <data alias="bodyText">
                <![CDATA[<p>This is some text</p>]]>
            </data>
            <data alias="showInMenu">1</data>
            <data alias="menuName">Menu Item 1</data>
        </node>     
        <node id="3" nodeTypeAlias="guide" nodeName="Menu Item 2" level="2">
            <data alias="bodyText">
                <![CDATA[<p>This is some text</p>]]>
            </data>
            <data alias="showInMenu">1</data>
            <data alias="menuName">Menu Item 2</data>
            <node id="4" nodeTypeAlias="guide" nodeName="Menu Item 2.1" level="3">
                <data alias="bodyText">
                    <![CDATA[<p>Some Text</p>]]>
                </data>
                <data alias="showInMenu">1</data>
                <data alias="menuName">Menu Item 2.1</data>
            </node>
            <node id="5" nodeTypeAlias="guide" nodeName="Menu Item 2.2" level="3">
                <data alias="bodyText">
                    <![CDATA[<p>Some Text</p>]]>
                </data>
                <data alias="showInMenu">1</data>
                <data alias="menuName">Menu Item 2.2</data>
                <node id="6" nodeTypeAlias="guide" nodeName="Item 2.2.1 Guide" level="4">
                    <data alias="bodyText">
                        <![CDATA[<p>Some Text</p>]]>
                    </data>
                    <data alias="showInMenu">0</data>
                    <data alias="menuName"></data>
                </node>
            </node>
        </node>     
        <node id="8" nodeTypeAlias="guide" nodeName="Menu Item 3" level="2">
            <data alias="bodyText">
                <![CDATA[<p>This is some text</p>]]>
            </data>
            <data alias="showInMenu">1</data>
            <data alias="menuName">Menu Item 3</data>
        </node>     
        <node id="9" nodeTypeAlias="guide" nodeName="Menu Item 4" level="2">
            <data alias="bodyText">
                <![CDATA[<p>This is some text</p>]]>
            </data>
            <data alias="showInMenu">1</data>
            <data alias="menuName">Menu Item 4</data>
        </node>     
    </node>
    <node id="7" nodeTypeAlias="someAlias" nodeName="Some Other Page" level="1">
        <data alias="bodyText">
            <![CDATA[<p>This is some text</p>]]>
        </data>         
    </node>     
</root>

编辑:以下内容几乎满足了我的需要:

<xsl:variable name="visibleChidren" select="node[data[@alias='showInMenu'] = 1 and (@level = 2 or descendant-or-self::*[generate-id($currentPage) = generate-id(.)] or preceding-sibling::*[generate-id($currentPage) = generate-id(.)] or following-sibling::*[generate-id($currentPage) = generate-id(.)])]" />

我只需要还包括当前页面的直接子级。

I've created a menu in umbraco using XSLT. The menu is using the usual ul and li elements and I'm displaying only the first level of the menu. The aim is to create a menu that expands to show the sub menu when I click a parent node (in the top level).

I am after the xslt I would need to expose the sub menu when clicked.

I think I would need to make use of ancestor-or-self to detect the current menu and parent menu and display them and also the $currentPage variable.

I have the following xslt:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<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" xmlns:tagsLib="urn:tagsLib" xmlns:urlLib="urn:urlLib" 
    exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets tagsLib urlLib ">

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

<xsl:param name="currentPage"/>

<xsl:template match="/">
    <div id="kb-categories"> 
        <h3>Categories</h3>
        <xsl:call-template name="drawNodes">  
            <xsl:with-param name="parent" select="$currentPage/ancestor-or-self::node [@level=1]"/>  
        </xsl:call-template>
    </div>
</xsl:template>

<xsl:template name="drawNodes">
    <xsl:param name="parent"/> 
    <xsl:if test="(umbraco.library:IsProtected($parent/@id, $parent/@path) = 0 or (umbraco.library:IsProtected($parent/@id, $parent/@path) = 1)) and $parent/@level = 1">           
        <ul class="kb-menuLevel1" >     
        <xsl:for-each select="$parent/node [string(./data [@alias='showInMenu']) = 1]"> 
            <li>  
                <a href="/kb{umbraco.library:NiceUrl(@id)}">
                    <xsl:value-of select="@nodeName"/>
                </a>                
                <xsl:variable name="level" select="@level" />
                <xsl:if test="(count(./node [string(./data [@alias='showInMenu']) = '1']) > 0)">   
                    <xsl:call-template name="drawNodes">    
                        <xsl:with-param name="parent" select="."/>    
                    </xsl:call-template>  
                </xsl:if> 
            </li> 
        </xsl:for-each>
        </ul>
    </xsl:if>
    <xsl:if test="(umbraco.library:IsProtected($parent/@id, $parent/@path) = 0 or (umbraco.library:IsProtected($parent/@id, $parent/@path) = 1)) and $parent/@level > 1">    
        <ul class="kb-menuLevel{@level}" style="display: none;">            
        <xsl:for-each select="$parent/node [string(./data [@alias='showInMenu']) = 1]"> 
            <li>  
                <a href="/kb{umbraco.library:NiceUrl(@id)}">
                    <xsl:value-of select="@nodeName"/>
                </a>                
                <xsl:variable name="level" select="@level" />
                <xsl:if test="(count(./node [string(./data [@alias='showInMenu']) = '1']) > 0)">   
                    <xsl:call-template name="drawNodes">    
                        <xsl:with-param name="parent" select="."/>    
                    </xsl:call-template>  
                </xsl:if> 
            </li>
        </xsl:for-each>
        </ul>
    </xsl:if>

</xsl:template>

</xsl:stylesheet>

I suspect this could be improved using apply-templates, but I'm not yet up to speed with that (this being only the second day of my learning xslt).

My menu:

  • Menu Item 1
  • Menu Item 2
  • Menu Item 3
  • Menu Item 4

when I click on Menu Item 2 I will be taken to the page for menu Item 2 and the submenu will also be displayed:

  • Menu Item 1
  • Menu Item 2
    -- Menu Item 2.1
    -- Menu Item 2.2
  • Menu Item 3
  • Menu Item 4

and so on down the nested menu.

Here is some sample xml for the above.

<root>  
    <node id="1" nodeTypeAlias="kbHomepage" nodeName="Home" level="1">
        <data alias="introduction">
            <![CDATA[<p>Welcome</p>]]>
        </data>
        <node id="2" nodeTypeAlias="guide" nodeName="Menu Item 1" level="2">
            <data alias="bodyText">
                <![CDATA[<p>This is some text</p>]]>
            </data>
            <data alias="showInMenu">1</data>
            <data alias="menuName">Menu Item 1</data>
        </node>     
        <node id="3" nodeTypeAlias="guide" nodeName="Menu Item 2" level="2">
            <data alias="bodyText">
                <![CDATA[<p>This is some text</p>]]>
            </data>
            <data alias="showInMenu">1</data>
            <data alias="menuName">Menu Item 2</data>
            <node id="4" nodeTypeAlias="guide" nodeName="Menu Item 2.1" level="3">
                <data alias="bodyText">
                    <![CDATA[<p>Some Text</p>]]>
                </data>
                <data alias="showInMenu">1</data>
                <data alias="menuName">Menu Item 2.1</data>
            </node>
            <node id="5" nodeTypeAlias="guide" nodeName="Menu Item 2.2" level="3">
                <data alias="bodyText">
                    <![CDATA[<p>Some Text</p>]]>
                </data>
                <data alias="showInMenu">1</data>
                <data alias="menuName">Menu Item 2.2</data>
                <node id="6" nodeTypeAlias="guide" nodeName="Item 2.2.1 Guide" level="4">
                    <data alias="bodyText">
                        <![CDATA[<p>Some Text</p>]]>
                    </data>
                    <data alias="showInMenu">0</data>
                    <data alias="menuName"></data>
                </node>
            </node>
        </node>     
        <node id="8" nodeTypeAlias="guide" nodeName="Menu Item 3" level="2">
            <data alias="bodyText">
                <![CDATA[<p>This is some text</p>]]>
            </data>
            <data alias="showInMenu">1</data>
            <data alias="menuName">Menu Item 3</data>
        </node>     
        <node id="9" nodeTypeAlias="guide" nodeName="Menu Item 4" level="2">
            <data alias="bodyText">
                <![CDATA[<p>This is some text</p>]]>
            </data>
            <data alias="showInMenu">1</data>
            <data alias="menuName">Menu Item 4</data>
        </node>     
    </node>
    <node id="7" nodeTypeAlias="someAlias" nodeName="Some Other Page" level="1">
        <data alias="bodyText">
            <![CDATA[<p>This is some text</p>]]>
        </data>         
    </node>     
</root>

edit: the following almost does what I need :

<xsl:variable name="visibleChidren" select="node[data[@alias='showInMenu'] = 1 and (@level = 2 or descendant-or-self::*[generate-id($currentPage) = generate-id(.)] or preceding-sibling::*[generate-id($currentPage) = generate-id(.)] or following-sibling::*[generate-id($currentPage) = generate-id(.)])]" />

I just need to also include the direct children from the current page.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

冷︶言冷语的世界 2024-09-06 05:09:46

我尝试(以我对 Umbraco 的了解非常有限)稍微清理一下你的代码并删除冗余。它看起来好像可以与您提供的 XML 示例一起使用,但我无法真正针对 Umbraco 进行测试。

<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<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" xmlns:tagsLib="urn:tagsLib" xmlns:urlLib="urn:urlLib"
  exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets tagsLib urlLib ">

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

  <xsl:param name="currentPage" />

  <xsl:template match="/">
    <div id="kb-categories">
      <h3>Categories</h3>
      <xsl:apply-templates mode="list" select="/root/node[@nodeTypeAlias='kbHomepage']" />
    </div>
  </xsl:template>

  <!-- matches anything with <node> children and creates an <ul> -->
  <xsl:template match="*[node]" mode="list">
    <!-- prepare a list of all visible children -->
    <xsl:variable name="visibleChidren" select="node[
      data[@alias='showInMenu'] = 1
      and (
        not(umbraco.library:IsProtected(@id, @path)) 
        or umbraco.library:IsLoggedOn() 
      )
    ]" />
    <!-- prepare a CSS class for the "selected path" -->
    <xsl:variable name="display">
      <xsl:if test=".//node[generate-id() = generate-id($currentPage)]">
        <xsl:text>visible</xsl:text>
      </xsl:if>
    </xsl:variable>
    <xsl:if test="$visibleChidren">
      <ul class="menu kb-menuLevel{$visibleChidren[1]/@level} {$display}">
        <xsl:apply-templates mode="item" select="$visibleChidren" />
      </ul>
    </xsl:if>
  </xsl:template>

  <!-- matches <node> elements and turns them into list items -->
  <xsl:template match="node" mode="item">
    <li>
      <xsl:if test="generate-id() = generate-id($currentPage)">
        <xsl:attribute name="class">selected</xsl:attribute>
      </xsl:if>
      <a href="/kb{{umbraco.library:NiceUrl(@id)}}">
        <xsl:value-of select="@nodeName" />
      </a>
      <!-- if there are any child nodes, render them -->
      <xsl:if test="node">
        <xsl:apply-templates mode="list" select="." />
      </xsl:if>
    </li>
  </xsl:template>

</xsl:stylesheet>

给你以下内容。请注意,我已经转义了 中的属性值模板 - 删除上面的双花括号以再次启用它们:

<div id="kb-categories">
  <h3>Categories</h3>
  <ul class="menu kb-menuLevel2 visible">
    <li>
      <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 1</a>
    </li>
    <li>
      <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 2</a>
      <ul class="menu kb-menuLevel3 visible">
        <li class="selected">
          <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 2.1</a>
        </li>
        <li>
          <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 2.2</a>
        </li>
      </ul>
    </li>
    <li>
      <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 3</a>
    </li>
    <li>
      <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 4</a>
    </li>
  </ul>
</div>

现在您可以在 CSS 中执行以下操作:

ul.menu {
  display: hidden;
}
ul.menu.visible {
  display: block;
}
ul.menu li.selected {
  font-weight: bold;
}

这对您有帮助吗?

I tried (with my very limited knowledge about Umbraco) to clean up your code a bit and remove the redundancy. It looks as though it would work with the XML sample you provided, but I cannot really test it against Umbraco.

<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<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" xmlns:tagsLib="urn:tagsLib" xmlns:urlLib="urn:urlLib"
  exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets tagsLib urlLib ">

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

  <xsl:param name="currentPage" />

  <xsl:template match="/">
    <div id="kb-categories">
      <h3>Categories</h3>
      <xsl:apply-templates mode="list" select="/root/node[@nodeTypeAlias='kbHomepage']" />
    </div>
  </xsl:template>

  <!-- matches anything with <node> children and creates an <ul> -->
  <xsl:template match="*[node]" mode="list">
    <!-- prepare a list of all visible children -->
    <xsl:variable name="visibleChidren" select="node[
      data[@alias='showInMenu'] = 1
      and (
        not(umbraco.library:IsProtected(@id, @path)) 
        or umbraco.library:IsLoggedOn() 
      )
    ]" />
    <!-- prepare a CSS class for the "selected path" -->
    <xsl:variable name="display">
      <xsl:if test=".//node[generate-id() = generate-id($currentPage)]">
        <xsl:text>visible</xsl:text>
      </xsl:if>
    </xsl:variable>
    <xsl:if test="$visibleChidren">
      <ul class="menu kb-menuLevel{$visibleChidren[1]/@level} {$display}">
        <xsl:apply-templates mode="item" select="$visibleChidren" />
      </ul>
    </xsl:if>
  </xsl:template>

  <!-- matches <node> elements and turns them into list items -->
  <xsl:template match="node" mode="item">
    <li>
      <xsl:if test="generate-id() = generate-id($currentPage)">
        <xsl:attribute name="class">selected</xsl:attribute>
      </xsl:if>
      <a href="/kb{{umbraco.library:NiceUrl(@id)}}">
        <xsl:value-of select="@nodeName" />
      </a>
      <!-- if there are any child nodes, render them -->
      <xsl:if test="node">
        <xsl:apply-templates mode="list" select="." />
      </xsl:if>
    </li>
  </xsl:template>

</xsl:stylesheet>

Gives you the following. Note that I have escaped the attribute value template in <a href... - remove the double curlies above to enable them again:

<div id="kb-categories">
  <h3>Categories</h3>
  <ul class="menu kb-menuLevel2 visible">
    <li>
      <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 1</a>
    </li>
    <li>
      <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 2</a>
      <ul class="menu kb-menuLevel3 visible">
        <li class="selected">
          <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 2.1</a>
        </li>
        <li>
          <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 2.2</a>
        </li>
      </ul>
    </li>
    <li>
      <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 3</a>
    </li>
    <li>
      <a href="/kb{umbraco.library:NiceUrl(@id)}">Menu Item 4</a>
    </li>
  </ul>
</div>

Now you could do in CSS:

ul.menu {
  display: hidden;
}
ul.menu.visible {
  display: block;
}
ul.menu li.selected {
  font-weight: bold;
}

Does that help you?

涙—继续流 2024-09-06 05:09:46

我明白了我需要做什么才能做我想做的事。关键行是:

<xsl:variable name="visibleChidren" select="node[data[@alias='showInMenu'] = 1 and (@level = 2 or descendant-or-self::*[generate-id($currentPage) = generate-id(.)] or preceding-sibling::*[generate-id($currentPage) = generate-id(.)] or following-sibling::*[generate-id($currentPage) = generate-id(.)] or parent::*[generate-id($currentPage) = generate-id(.)])]" />

从整个 xslt 来看:

<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<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" xmlns:tagsLib="urn:tagsLib" xmlns:urlLib="urn:urlLib"
  exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets tagsLib urlLib ">

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

  <xsl:param name="currentPage"/>
  <xsl:variable name="currentLevel" select="$currentPage/@level" />

  <xsl:template match="/">
    <div id="kb-categories">
      <h3>Categories</h3>
      <xsl:apply-templates mode="list" select="$currentPage/ancestor-or-self::node [@nodeTypeAlias = 'kbHomepage']" />
    </div>
  </xsl:template>

  <!-- matches anything with <node> children and makes a list out of them -->
  <xsl:template match="node" mode="list">
    <!-- select only sub-nodes that have 'showInMenu' = 1 -->
    <xsl:variable name="visibleChidren" select="node[data[@alias='showInMenu'] = 1 and (@level = 2 or descendant-or-self::*[generate-id($currentPage) = generate-id(.)] or preceding-sibling::*[generate-id($currentPage) = generate-id(.)] or following-sibling::*[generate-id($currentPage) = generate-id(.)] or parent::*[generate-id($currentPage) = generate-id(.)])]" />
    <xsl:if test="$visibleChidren">
      <ul>
        <xsl:apply-templates mode="item" select="$visibleChidren" />
      </ul>
    </xsl:if>
  </xsl:template>

  <xsl:template match="node" mode="item">
      <li>
        <a href="/kb{umbraco.library:NiceUrl(@id)}">
          <xsl:value-of select="@nodeName"/>
        </a>
        <xsl:apply-templates mode="list" select="." />
      </li>
  </xsl:template>

</xsl:stylesheet>

I figured out what I need to do what I want. The key line being:

<xsl:variable name="visibleChidren" select="node[data[@alias='showInMenu'] = 1 and (@level = 2 or descendant-or-self::*[generate-id($currentPage) = generate-id(.)] or preceding-sibling::*[generate-id($currentPage) = generate-id(.)] or following-sibling::*[generate-id($currentPage) = generate-id(.)] or parent::*[generate-id($currentPage) = generate-id(.)])]" />

From the entire xslt:

<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<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" xmlns:tagsLib="urn:tagsLib" xmlns:urlLib="urn:urlLib"
  exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets tagsLib urlLib ">

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

  <xsl:param name="currentPage"/>
  <xsl:variable name="currentLevel" select="$currentPage/@level" />

  <xsl:template match="/">
    <div id="kb-categories">
      <h3>Categories</h3>
      <xsl:apply-templates mode="list" select="$currentPage/ancestor-or-self::node [@nodeTypeAlias = 'kbHomepage']" />
    </div>
  </xsl:template>

  <!-- matches anything with <node> children and makes a list out of them -->
  <xsl:template match="node" mode="list">
    <!-- select only sub-nodes that have 'showInMenu' = 1 -->
    <xsl:variable name="visibleChidren" select="node[data[@alias='showInMenu'] = 1 and (@level = 2 or descendant-or-self::*[generate-id($currentPage) = generate-id(.)] or preceding-sibling::*[generate-id($currentPage) = generate-id(.)] or following-sibling::*[generate-id($currentPage) = generate-id(.)] or parent::*[generate-id($currentPage) = generate-id(.)])]" />
    <xsl:if test="$visibleChidren">
      <ul>
        <xsl:apply-templates mode="item" select="$visibleChidren" />
      </ul>
    </xsl:if>
  </xsl:template>

  <xsl:template match="node" mode="item">
      <li>
        <a href="/kb{umbraco.library:NiceUrl(@id)}">
          <xsl:value-of select="@nodeName"/>
        </a>
        <xsl:apply-templates mode="list" select="." />
      </li>
  </xsl:template>

</xsl:stylesheet>
追我者格杀勿论 2024-09-06 05:09:46

或者您可以解决 XSLT 中的大量黑客问题,并使用 our.umbraco.org 中的以下导航包,

我认为这可以满足您所需的一切,而无需在 XSLT 的黑暗世界中亲自动手。

http://our.umbraco.org/projects/cogworks---flexible-导航

Or you could solve yourself a lot of hacking about in XSLT and use the following navigation package from our.umbraco.org

This I think does everything you need and no need to get your hands dirty in the murky world of XSLT.

http://our.umbraco.org/projects/cogworks---flexible-navigation

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文