【问题标题】:XSLT 1.0: Generating an ancestor menu hierarchyXSLT 1.0:生成祖先菜单层次结构
【发布时间】:2013-03-01 12:23:50
【问题描述】:

这应该很简单!我有一个包含菜单层次结构的 XML 文档:

<?xml version="1.0" encoding="utf-8"?>
<menu page_id="18" language="en-GB">
    <item id="1" child_of="0">
        <menu_order>1</menu_order>
        <title><![CDATA[Home]]></title>
    </item>
    <item id="18" child_of="0">
        <title><![CDATA[Page One]]></title>
        <submenu child_of="18">
            <item id="20" child_of="18">
                <title><![CDATA[Sub Menu One]]></title>
                <submenu child_of="20">
                    <item id="26" child_of="20">
                        <title><![CDATA[SubMenu 1-1]]></title>
                    </item>
                    <item id="27" child_of="20">
                        <title><![CDATA[SubMenu 1-2]]></title>
                    </item>
                </submenu>
            </item>
            <item id="21" child_of="18">
                <title><![CDATA[Sub Menu Two]]></title>
                <submenu child_of="21">
                    <item id="28" child_of="21">
                        <title><![CDATA[SubMenu 2-1]]></title>
                    </item>
                    <item id="29" child_of="21">
                        <title><![CDATA[SubMenu 2-2]]></title>
                        <submenu child_of="29">
                            <item id="32" child_of="29">
                                <title><![CDATA[SubMenu 2-2-1]]></title>
                            </item>
                            <item id="33" child_of="29">
                                <title><![CDATA[SubMenu 2-2-2]]></title>
                            </item>
                        </submenu>
                    </item>
                    <item id="30" child_of="21">
                        <title><![CDATA[SubMenu 2-3]]></title>
                    </item>
                    <item id="31" child_of="21">
                        <title><![CDATA[SubMenu 2-4]]></title>
                    </item>
                </submenu>
            </item>
            <item id="22" child_of="18">
                <title><![CDATA[Sub Menu Three]]></title>
            </item>
        </submenu>
    </item>
    <item id="19" child_of="0">
        <title><![CDATA[Page Two]]></title>
    </item>
</menu>

我需要将它转换为一个 HTML 列表,其中 (1) 如果活动/单击的菜单项有一个子菜单,它会在其下方显示子菜单(仅菜单的子项)。例如,点击 item id = "18" 应该给我这个:

<ul>
    <li id="1">Home</li>
    <li id="18">Page One
        <ul>
            <li id="20">Sub Menu One</li>
            <li id="21">Sub Menu Two</li>
            <li id="22">Sub Menu Three</li>
        </ul>
    </li>
    <li id="19">Page Two</li>
</ul>

或者 (2) 如果活动菜单项有祖先,它会在结构中呈现其所有直接同级和祖先。例如,单击 item id="33" 应该给我这个:

<ul>
    <li id="1">Home</li>
    <li id="18">Page One<ul>
            <li id="20">Sub Menu One</li>
            <li id="21">Sub Menu Two<ul>
                    <li id="28">SubMenu 2-1</li>
                    <li id="29">SubMenu 2-2
                        <ul>
                            <li id="32">SubMenu 2-2-1</li>
                            <li id="33">SubMenu 2-2-2</li>
                        </ul>
                    </li>
                    <li id="30">SubMenu 2-3</li>
                    <li id="31">SubMenu 2-4</li>
                </ul>
            </li>
            <li id="22">Sub Menu Three</li>
        </ul>
    </li>
    <li id="19">Page Two</li>
</ul>

我的问题是我的 XSL 样式表生成了一个包含两个祖先子菜单的列表!请帮忙......我已经在这几个小时了!这是我的 XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output indent="yes"/>
    <!-- The DOM ID of the active menu item -->
    <xsl:param name="activeItemID"/>

    <xsl:template match="text()">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="menu">
        <ul>
            <xsl:choose>
                <xsl:when test="//item[@id = $activeItemID]/@child_of = '0'">
                    <xsl:choose>
                        <xsl:when test="//submenu[@child_of = $activeItemID]/node()">
                            <xsl:apply-templates
                                select="//item[@child_of = '0'] | //submenu[@child_of = $activeItemID]"/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:apply-templates select="//item[@child_of = '0']"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:choose>
                        <xsl:when test="//submenu[@child_of = $activeItemID]/node()">
                            <xsl:apply-templates
                                select="//item[@child_of = '0'] | //submenu[@child_of = $activeItemID]/ancestor-or-self::submenu/item"
                            />
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:apply-templates
                                select="//item[@child_of = '0'] | //item[@id = $activeItemID]/ancestor-or-self::submenu"
                            />
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:otherwise>
            </xsl:choose>
        </ul>
    </xsl:template>

    <xsl:template match="item">
        <li>
            <xsl:value-of select="title" disable-output-escaping="no"/>
            <xsl:apply-templates select="submenu[@child_of = $activeItemID]"/>
        </li>
    </xsl:template>

    <xsl:template match="submenu">
        <ul>
            <xsl:apply-templates select="item[@child_of = $activeItemID]">
                <xsl:sort select="menu_order" data-type="number"/>
            </xsl:apply-templates>
        </ul>
    </xsl:template>

</xsl:stylesheet>

【问题讨论】:

    标签: xslt xslt-1.0


    【解决方案1】:

    这个 XSLT 应该做你想做的事:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:output indent="yes"/>
      <!-- The DOM ID of the active menu item -->
      <xsl:param name="activeItemID" />
    
      <xsl:template match="menu | submenu">
        <ul>
          <xsl:apply-templates select="item" />
        </ul>
      </xsl:template>
    
      <xsl:template match="item">
        <li id="{@id}">
          <xsl:value-of select="title" />
          <xsl:apply-templates select="submenu[..//@id = $activeItemID]"/>
        </li>
      </xsl:template>
    </xsl:stylesheet>
    

    在参数值为 18 的示例输入上运行时,它会产生:

    <ul>
      <li id="1">Home</li>
      <li id="18">
        Page One<ul>
          <li id="20">Sub Menu One</li>
          <li id="21">Sub Menu Two</li>
          <li id="22">Sub Menu Three</li>
        </ul>
      </li>
      <li id="19">Page Two</li>
    </ul>
    

    当参数值为33运行时,会产生:

    <ul>
      <li id="1">Home</li>
      <li id="18">
        Page One<ul>
          <li id="20">Sub Menu One</li>
          <li id="21">
            Sub Menu Two<ul>
              <li id="28">SubMenu 2-1</li>
              <li id="29">
                SubMenu 2-2<ul>
                  <li id="32">SubMenu 2-2-1</li>
                  <li id="33">SubMenu 2-2-2</li>
                </ul>
              </li>
              <li id="30">SubMenu 2-3</li>
              <li id="31">SubMenu 2-4</li>
            </ul>
          </li>
          <li id="22">Sub Menu Three</li>
        </ul>
      </li>
      <li id="19">Page Two</li>
    </ul>
    

    您的 XSLT 有一些排序逻辑,但用于排序的元素似乎只存在于源 XML 中的一个位置。那是你想用的东西吗?为了简单起见,您是否省略了源 XML 中的大部分 menu_order 元素?

    【讨论】:

    • @JLRische:非常感谢!这完美地工作,正是我所需要的。是的,我在完整版中确实有一些排序逻辑,但错误地在示例中留下了一些节点。再次感谢。
    • 请问如何使用 XSLT 生成菜单结构的变体,即排除 @child_of = '0' 的项目?谢谢。
    猜你喜欢
    • 2015-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    相关资源
    最近更新 更多