2011-08-11 68 views
1

我对XSL转换(XSLT-1)有疑问。我尝试了几天,但我没有得到它的工作。XSLT导航菜单

我想用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> 

现在我想调用一个页面有$的pageid = 7发送的URL,它应该表现出一些像这样的输出:

<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 = 4的URL发送,它应该表现出一些像这样的输出:

<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帮助我吗?

或者也许有人已经有一个工作解决方案在这里发布?

它会很亲切。谢谢大家的关注。

回答

2

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

"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> 
+0

@Eddy感谢您的反馈我已经更新了相应的问题。现在支持升序/降序并适用于'xsl:call-template'。注意我使用了模板模式来简化递归。 –

+1

很多人感谢你@empo! 这是一个很好的工作,我永远不会发现钩与“模式” - 属于我自己。我学到了一些非常重要的知识! –

1

我认为逻辑是,如果一个项目选择的页面作为后代,或者是选定的页面,那么你想看到该项目的所有子项目。

这是我尝试...

<?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> 
+0

我认为你对通缉逻辑是真实的。我可能误解了这个要求。 +1 –

+1

我已经修复了我的测试条件。为什么在只有一个测试时使用'xsl:choose'? –

+0

@empo是的,你是对的!当我开始写它时,我想我需要一个单独的条件为后代和匹配项目本身。最后,我将测试合并到一个测试中,但忽略了将测试合并到xsl中:if –