【问题标题】:XSLT Navigation MenuXSLT 导航菜单
【发布时间】:2011-08-11 02:15:18
【问题描述】:

我有一个关于 XSL 转换 (XSLT-1) 的问题。几天以来我一直在尝试它,但我没有让它工作。

我想用 XML 和 XSLT-1 构建一个标准的网站树形导航。它应该只显示当前项目路径上的项目。如果当前项有子项,则应打开下一个节点。

我的 XML 源是这样的:

<cat>
    <item id="0" name="1">
        <item id="1" name="1.1"></item>
        <item id="2" name="1.2"></item>
        <item id="3" name="1.3"></item>
        <item id="4" name="1.4">
            <item id="5" name="1.4.1">
                <item id="6" name="1.4.1.1"></item>
                <item id="7" name="1.4.1.2"></item>
                <item id="8" name="1.4.1.3"></item>
            </item>
            <item id="9" name="1.4.2"></item>
            <item id="10" name="1.4.3"></item>
        </item>
        <item id="11" name="1.5"></item>
        <item id="12" name="1.6"></item>
    </item>
    <item id="13" name="2">
        <item id="14" name="2.1"></item>
        <item id="15" name="2.2"></item>
    </item>
    <item id="16" name="3"></item>
</cat>

现在我想调用一个通过 URL 发送的带有 $pageid=7 的页面,它应该显示如下输出:

<ul>
    <li>1
        <ul>
            <li>1.1</li>
            <li>1.2</li>
            <li>1.3</li>
            <li>1.4
                <ul>
                    <li>1.4.1
                        <ul>
                            <li>1.4.1.1</li>
                            <li class="activeitem">1.4.1.2</li>
                            <li>1.4.1.3</li>
                        </ul>
                    </li>
                    <li>1.4.2</li>
                    <li>1.4.3</li>
                </ul>
            </li>
            <li>1.5</li>
            <li>1.6</li>
        </ul>
    </li>
    <li>2</li>
    <li>3</li>
</ul>

如果我调用一个通过 URL 发送的带有 $pageid=4 的页面,它应该显示如下输出:

<ul>
    <li>1
        <ul>
            <li>1.1</li>
            <li>1.2</li>
            <li>1.3</li>
            <li class="activeitem">1.4
                <ul>
                    <li>1.4.1</li>
                    <li>1.4.2</li>
                    <li>1.4.3</li>
                </ul>
            </li>
            <li>1.5</li>
            <li>1.6</li>
        </ul>
    </li>
    <li>2</li>
    <li>3</li>
</ul>

希望我的例子能被所有人理解。

我已经有了一个站点地图和一个面包屑导航,但这个似乎非常棘手和经验丰富。

我尝试修改 Tree navigation with XML and XSLT 中的示例 - 但效果不佳。它只显示项目的路径,而不显示其余部分。

有 XSLT-1 方面经验的人可以帮我解决吗?

或者也许有人已经有一个可行的解决方案可以在这里发布?

这将是非常友好的。谢谢大家的关注。

【问题讨论】:

    标签: xml xslt xhtml tree navigation


    【解决方案1】:

    这里的挑战是找到在新列表中导航的正确测试。对于给定的列表项,我认为您正在搜索这种测试(不是很明显):

     "item and .//@id=$pageid"
    

    检查这个转换。

    [XSLT 1.0]

     <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:output indent="yes"/>
        <xsl:param name="pageid" select="4"/>
    
        <xsl:template match="/">
            <xsl:call-template name="Navigate"/>
        </xsl:template>
    
        <xsl:template name="Navigate">
            <ul>
                <xsl:apply-templates select="/cat/item" mode="Navigate"/>
            </ul>
        </xsl:template>
    
        <xsl:template match="item" mode="Navigate">
            <li>
                <xsl:apply-templates select="@id[.=$pageid]" mode="Navigate"/>
                <xsl:value-of select="@name"/>
                <xsl:if test="item and .//@id=$pageid">
                    <ul>
                        <xsl:apply-templates select="item" mode="Navigate"/>
                    </ul>
                </xsl:if>
            </li>
        </xsl:template>
    
        <xsl:template match="@id" mode="Navigate">
            <xsl:attribute name="class">
                <xsl:value-of select="'activeitem'"/>
            </xsl:attribute>
        </xsl:template>
    
    </xsl:stylesheet>
    

    $pageid = 4 的结果:

    <ul>
       <li>1<ul>
             <li>1.1</li>
             <li>1.2</li>
             <li>1.3</li>
             <li class="activeitem">1.4<ul>
                   <li>1.4.1</li>
                   <li>1.4.2</li>
                   <li>1.4.3</li>
                </ul>
             </li>
             <li>1.5</li>
             <li>1.6</li>
          </ul>
       </li>
       <li>2</li>
       <li>3</li>
    </ul>
    

    $pageid=7 的结果:

    <ul>
       <li>1<ul>
             <li>1.1</li>
             <li>1.2</li>
             <li>1.3</li>
             <li>1.4<ul>
                   <li>1.4.1<ul>
                         <li>1.4.1.1</li>
                         <li class="activeitem">1.4.1.2</li>
                         <li>1.4.1.3</li>
                      </ul>
                   </li>
                   <li>1.4.2</li>
                   <li>1.4.3</li>
                </ul>
             </li>
             <li>1.5</li>
             <li>1.6</li>
          </ul>
       </li>
       <li>2</li>
       <li>3</li>
    </ul>
    

    $pageid=13 的结果:

    <ul>
       <li>1</li>
       <li class="activeitem">2<ul>
             <li>2.1</li>
             <li>2.2</li>
          </ul>
       </li>
       <li>3</li>
    </ul>
    

    【讨论】:

    • @Eddy 感谢您的反馈,我已相应地更新了问题。现在支持升序/降序并适应xsl:call-template。注意我使用模板模式来简化递归。
    • 非常感谢@empo!这个工作得很好,我永远不会找到带有“模式”的钩子——我自己的属性。我学到了一些非常重要的知识!
    【解决方案2】:

    我认为逻辑是,如果一个项目将所选页面作为后代,或者是所选页面,那么您希望查看该项目的所有子项目。

    这是我的尝试...

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
       <xsl:output method="xml" indent="yes"/>
       <xsl:param name="pageNum" select="13" />
    
       <xsl:template match="/cat">
          <ul>
             <xsl:apply-templates />
          </ul>
       </xsl:template>
    
       <xsl:template match="item">
          <li>
             <xsl:if test="@id=$pageNum">
                <xsl:attribute name="class">activeitem</xsl:attribute>
             </xsl:if>
             <xsl:value-of select="@name" />
             <xsl:choose>
                <xsl:when test="descendant-or-self::item[@id=$pageNum] and count(node()) > 0">
                   <ul>
                      <xsl:apply-templates />
                   </ul>
                </xsl:when>
             </xsl:choose>
          </li>
       </xsl:template>
    </xsl:stylesheet>
    

    对于 4 和 7,预期输出如问题所示。对于13,输出如下:

    <ul>
        <li>1</li>
        <li class="activeitem">2
            <ul>
                <li>2.1</li>
                <li>2.2</li>
            </ul>
        </li>
        <li>3</li>
    </ul>
    

    【讨论】:

    • 我认为你对想要的逻辑是正确的。我可能误解了要求。 +1
    • 我已经相应地修正了我的测试条件。当你只有一个测试时,为什么要使用xsl:choose
    • @empo 是的,你是对的!当我开始写它时,我想我需要一个单独的后代条件和匹配项目本身。最后,我将测试合二为一,但忽略了将其设置为 xsl:if
    • 首先我要感谢@empo 和 Tim C 所做的工作,但我没能成功。我需要一个通过调用模板而不是通过分配模板包含的版本。 empo 的版本似乎只有在 id 是升序的情况下才有效。现在我尝试了这样的事情,但我没有得到真正的递归工作。
    • 也许有一个带有选择部分或 for-each 的解决方案。我以不同的方式尝试了这两种方法,但我得到的只是废话或无限循环。
    猜你喜欢
    • 2021-04-10
    • 1970-01-01
    • 2018-02-14
    • 2017-05-23
    • 2016-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多