【问题标题】:DotNetNuke + XPath = Custom navigation menuDotNetNuke + XPath = 自定义导航菜单
【发布时间】:2009-12-21 10:47:10
【问题描述】:

我正在使用 DNN Done Right 菜单组件为 DotNetNuke 5 开发皮肤,该组件使用自定义 XSL-T 将 XML 站点地图转换为 HTML 导航。

与其他构建导航菜单的方法相比,使用 XSL-T 是一种救命稻草。但是我在做一些更复杂的事情时遇到了问题,因为我是 XML-T 和 XPath 的新手。

我想要实现的是:

  • 忽略 0 级节点
  • 循环遍历所选层次结构中的所有 1 级节点
  • 找到选定的 1 级节点后,开始循环遍历层次结构/面包屑结构直至活动级别。
  • 一旦在活动节点级别,循环显示该级别的所有兄弟节点
  • 然后完成 1 级节点的循环

下面是菜单组件使用的站点地图的示例 XML 块。

<Root>
    <root>
        <node id="37" text="Home" url="http://www.dnndoneright.com/Home.T37.aspx" enabled="1" selected="0" breadcrumb="0" first="1" last="0" only="0" depth="0" >
            <description >Upgrade your standard DNN menu - automatically and for free - to an SEO-optimised, accessible, mobile-friendly, cross-browser menu.</description>
        </node>

        <node id="56" text="DNN Menu" url="http://www.dnndoneright.com/DNN-Menu.T56.aspx" enabled="1" selected="0" breadcrumb="1" first="0" last="0" only="0" depth="0" >
            <node id="97" text="Menu features" url="http://www.dnndoneright.com/Menu-features.T97.aspx" enabled="1" selected="0" breadcrumb="0" first="1" last="0" only="0" depth="1" />
            <node id="111" text="Pre-built templates" url="http://www.dnndoneright.com/Pre-built-templates.T111.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="0" only="0" depth="1" >
                <node id="94" text="Standard DNN menu, upgraded" url="http://www.dnndoneright.com/Standard-DNN-menu-upgraded.T94.aspx" enabled="1" selected="0" breadcrumb="0" first="1" last="0" only="0" depth="2" />
                <node id="124" text="Superfish template" url="http://www.dnndoneright.com/Superfish-template.T124.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="0" only="0" depth="2" />
                <node id="106" text="Treeview template" url="http://www.dnndoneright.com/Treeview-template.T106.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="0" only="0" depth="2" />
                <node id="107" text="Accordion template" url="http://www.dnndoneright.com/Accordion-template.T107.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="0" only="0" depth="2" />
                <node id="112" text="Dropdown template" url="http://www.dnndoneright.com/Dropdown-template.T112.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="0" only="0" depth="2" />
                <node id="96" text="Mega-menu" url="http://www.dnndoneright.com/Mega-menu.T96.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="1" only="0" depth="2" />
            </node>
            <node id="113" text="Getting started" url="http://www.dnndoneright.com/Getting-started.T113.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="0" only="0" depth="1" >
                <node id="114" text="Installing the menu" url="http://www.dnndoneright.com/Installing-the-menu.T114.aspx" enabled="1" selected="0" breadcrumb="0" first="1" last="0" only="0" depth="2" />
                <node id="115" text="Upgrading a SolPart menu" url="http://www.dnndoneright.com/Upgrading-a-SolPart-menu.T115.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="0" only="0" depth="2" />
                <node id="116" text="Upgrading a DNNMenu" url="http://www.dnndoneright.com/Upgrading-a-DNNMenu.T116.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="0" only="0" depth="2" />
                <node id="117" text="Installing a template" url="http://www.dnndoneright.com/Installing-a-template.T117.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="0" only="0" depth="2" />
                <node id="118" text="Adding to a skin" url="http://www.dnndoneright.com/Adding-to-a-skin.T118.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="1" only="0" depth="2" />
            </node>
            <node id="119" text="Customising templates" url="http://www.dnndoneright.com/Customising-templates.T119.aspx"   enabled="0" selected="0" breadcrumb="1" first="0" last="1" only="0" depth="1" >
                <node id="120" text="Standard options" url="http://www.dnndoneright.com/Standard-options.T120.aspx"         enabled="1" selected="0" breadcrumb="0" first="1" last="0" only="0" depth="2" />
                <node id="121" text="Specifying filenames" url="http://www.dnndoneright.com/Specifying-filenames.T121.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="0" only="0" depth="2" />
                <node id="122" text="XML format" url="http://www.dnndoneright.com/XML-format.T122.aspx"                     enabled="1" selected="1" breadcrumb="1" first="0" last="0" only="0" depth="2" />
                <node id="123" text="Creating custom templates" url="http://www.dnndoneright.com/Creating-custom-templates.T123.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="1" only="0" depth="2" />
            </node>
        </node>

        <node id="87" text="Download" url="http://www.dnndoneright.com/Download.T87.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="0" only="0" depth="0" />

        <node id="85" text="Contact" url="http://www.dnndoneright.com/Contact.T85.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="1" only="0" depth="0" >
            <node id="129" text="Blog" url="http://www.dnndoneright.com/Blog.T129.aspx" enabled="1" selected="0" breadcrumb="0" first="1" last="0" only="0" depth="1" />
            <node id="130" text="Forum" url="http://www.dnndoneright.com/Forum.T130.aspx" enabled="1" selected="0" breadcrumb="0" first="0" last="1" only="0" depth="1" />
        </node>
    </root>
</Root> 

这也是我的(不正确的)起点,只是为了暴露我缺乏 XSL/XPath 知识。 (我的代码是错误的,因为它列出了所有 L1 节点,而不仅仅是所选层次结构中的 L1 节点)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" />

    <xsl:template match="/">
    <div class="SideMenu">
      <!-- Loop through all L1 nodes -->
      <xsl:for-each select="Root/root/node/node">
        <xsl:if test="@enabled='1'" >
          <!-- Only use L1 in the current hierarchy -->

          <div>
            [ <xsl:value-of select="@text"/>: <xsl:value-of select="@depth"/> ]
          </div>
        </xsl:if>
      </xsl:for-each>
    </div>
    </xsl:template>

</xsl:stylesheet>

【问题讨论】:

  • 提示:请不要将 XML 声明与 XML 代码示例一起发布。声明中的编码 (ISO-8859-1) 和实际编码(UTF-8,与网页的其余部分一样)不同。
  • 已删除 XML 声明

标签: xml xslt xpath dotnetnuke


【解决方案1】:

以下假设输入中只能有一个选定节点:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:template match="/">
    <div class="SideMenu">
      <!-- select all the siblings of the selected node -->
      <xsl:apply-templates select="//node[@selected=1]/../node" />
    </div>
  </xsl:template>

  <!-- nodes are turned into a <div> with some descriptive text -->
  <xsl:template match="node">
    <div>
      <xsl:value-of select="concat('[ ', @text, ': ', ' ]')" />
    </div>
  </xsl:template>

</xsl:stylesheet>

示例 XML 的输出:

<div class="SideMenu">
  <div>[ Standard options: ]</div>
  <div>[ Specifying filenames: ]</div>
  <div>[ XML format: ]</div>
  <div>[ Creating custom templates: ]</div>
</div>

嵌套菜单很容易创建,但不可否认,我不太确定您想要什么。如果您发布所需的输出,我可以看到它。

【讨论】:

    【解决方案2】:

    如果您可以发布您希望看到的实际输出,那么它会有所帮助,但我认为您可能想要这样的东西:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:template match="root">
        <div class="SideMenu">
          <!-- Loop through level 1 nodes -->
          <xsl:apply-templates select="//node[@depth=1]" mode="general" />
        </div>
      </xsl:template>
    
      <xsl:template match="node" mode="general">
        <xsl:choose>
          <!-- If the currently selected node, show all siblings -->
          <xsl:when test="@selected=1">
            <xsl:apply-templates select="../node" mode="only" />
          </xsl:when>
          <!-- Otherwise show just this node -->
          <xsl:otherwise>
            <xsl:apply-templates select="." mode="only" />
          </xsl:otherwise>
        </xsl:choose>
        <!-- Follow the breadcrumb down towards the currently selected node -->
        <xsl:apply-templates select="node[@breadcrumb=1]" mode="general" />
      </xsl:template>
    
      <xsl:template match="node" mode="only">
        <div>
          [ <xsl:value-of select="@text"/>: <xsl:value-of select="@depth"/> ]
        </div>
      </xsl:template>
    </xsl:stylesheet>
    

    如果这不能满足您的需求,请随时在 DNNDoneRight 论坛上提问,这就是他们的目的!

    【讨论】:

      【解决方案3】:

      感谢您的回复。不幸的是,您的代码并不是我所需要的(很可能是由于我所追求的复杂性以及我无法解释我的要求)-但是由于您的示例代码,我对 XSL 有了更深入的了解- T 并创建了以下内容:

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
       <xsl:output method="html" />
      
       <xsl:template match="/">
          <div class="SideMenu">
            <!-- Loop through all L1 nodes -->
            <xsl:for-each select="Root/root/node">
              <xsl:if test="@enabled='1'" >
                <xsl:if test="@breadcrumb='1'" >
                  <!-- Find active root node-->
                  <!-- L0 nodes: Don't ever show (These are the horizontal tabs) -->
      
                  <!-- Always show all children: L1 nodes -->
                  <xsl:apply-templates select="child::node()[@url]" mode="BaseNode" ></xsl:apply-templates>
      
                </xsl:if>
              </xsl:if>
            </xsl:for-each>
          </div>
       </xsl:template>
      
        <!-- Template: Base node -->
        <xsl:template match="node" mode="BaseNode" >
      
          <xsl:choose>
            <xsl:when test="@breadcrumb='0'" >
              <!-- Non-breadcrumb L1 node -->
              <xsl:apply-templates select="." mode="NonShadedNode" ></xsl:apply-templates>
      
            </xsl:when>
            <xsl:when test="@breadcrumb='1'" >
              <!-- Child which is part of hierarchy -->
              <xsl:apply-templates select="." mode="ShadedNode" ></xsl:apply-templates>
      
              <!-- Drill down through hierarchy of active nodes-->
              <xsl:for-each select="descendant::node()[@url]">
                <xsl:if test="@breadcrumb='1'" >
      
                  <!-- Is this the last node? If so, show children -->
                  <xsl:choose>
                    <xsl:when test="child::node()[@url]">
                        <!-- Not last node -->
                      <xsl:apply-templates select="." mode="ShadedNode" ></xsl:apply-templates>
      
                    </xsl:when>
                    <xsl:otherwise>
                      <!-- Last node: loop through all siblings -->
      
                      <!-- THIS LOOP DOESN'T WORK CORRECTLY -->
                      <xsl:for-each select="preceding-sibling::node()" >
                        <xsl:apply-templates select="." mode="ShadedNode" ></xsl:apply-templates>
                      </xsl:for-each>
      
                      <xsl:apply-templates select="." mode="SelectedNode" ></xsl:apply-templates>
      
                      <xsl:for-each select="following-sibling::node()" >
                        <xsl:apply-templates select="." mode="ShadedNode" ></xsl:apply-templates>
                      </xsl:for-each>
      
                    </xsl:otherwise>
                  </xsl:choose>
      
                </xsl:if>
              </xsl:for-each>
      
            </xsl:when>
          </xsl:choose>
      
        </xsl:template>
      
        <!-- Template: Non-shaded node -->
        <xsl:template match="node" mode="NonShadedNode" >
          <a>
            <xsl:attribute name="href">
              <xsl:value-of select="@url"/>
            </xsl:attribute>
            <xsl:attribute name="style">
              padding-left:<xsl:value-of select="@depth * 10"/>
            </xsl:attribute>
            <xsl:value-of select="@text"/>
          </a>
        </xsl:template>
      
        <!-- Template: Shaded node -->
        <xsl:template match="node" mode="ShadedNode" >
          <a class="SideMenu_Shaded">
            <xsl:attribute name="href">
              <xsl:value-of select="@url"/>
            </xsl:attribute>
            <xsl:attribute name="style">
              padding-left:<xsl:value-of select="@depth * 10"/>
            </xsl:attribute>
            <xsl:value-of select="@text"/>
          </a>
        </xsl:template>
      
        <!-- Template: Selected node -->
        <xsl:template match="node" mode="SelectedNode" >
          <a class="SideMenu_Selected">
            <xsl:attribute name="style">
              padding-left:<xsl:value-of select="@depth * 10"/>
            </xsl:attribute>
            <xsl:value-of select="@text"/>
          </a>
        </xsl:template>
      
      </xsl:stylesheet>
      

      这正是我所需要的,除了 THESN'T WORK FORCORRECTLY 部分由于某种原因还显示了将兄弟姐妹分开的节点......我目前正在查看这个并希望它是我的代码中有一个小错误。

      如果你能发现问题,请告诉我! :)

      这是来自 XSL-T 的渲染 HTML:

      <div class="SideMenu"><a href="/Home/Tester.aspx" style="&#xA;        padding-left:10">Tester </a><a class="SideMenu_Shaded" href="/Home/ChiefConstablesArea.aspx" style="&#xA;        padding-left:10">Chief Constables Area</a>
          Chief Constables Area
          Chief Constables Area
          <a class="SideMenu_Shaded" href="/Home/ChiefConstablesArea/ChiefsFocusGroups.aspx" style="&#xA;        padding-left:20">Chief's Focus Groups</a>
          <a class="SideMenu_Shaded" href="/Home/ChiefConstablesArea/AbouttheChief.aspx" style="&#xA;        padding-left:20">About the Chief</a>
          <a class="SideMenu_Shaded" href="/Home/ChiefConstablesArea/ChiefsOfficerGroup.aspx" style="&#xA;        padding-left:20">Chief's Officer Group</a>
          <a class="SideMenu_Selected" style="&#xA;        padding-left:20">Chief's Messages</a>
          <a class="SideMenu_Shaded" href="/Home/ChiefConstablesArea/ForceAwardsScheme.aspx" style="&#xA;        padding-left:20">Force Awards Scheme</a>
        <a href="/Home/ActiveForumLitetrial.aspx" style="&#xA;        padding-left:10">Active Forum Lite trial</a></div>
      

      【讨论】:

      • 需要
      猜你喜欢
      • 2011-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-26
      • 1970-01-01
      相关资源
      最近更新 更多