我最近问了一个问题,哪个引擎要解析我的xml并决定坚持使用XSL,但我只能把工作完成一半。 (参考:Which language to use to parse xml for navigation)
我已经成功地走了<root> --> <menu> --> <nav>
,但任何导航和逻辑下的孩子都完全搞砸了。
问题是当@path是下一个子节点层时,如何在xsl中重复我的逻辑以深入xml子节点?
我甚至做得对吗?我觉得我在这里错过了什么,应该以某种方式使用模板?
例如,这是我的xsl样式表。
<?xml version="1.0" encoding="UTF-8"?>
<!--
Document : sitemap.xsl
Created on : 2 February 2011, 14:53
Author : Jared
Description:
Purpose of transformation follows.
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:param name="page" select="default"/>
<xsl:template match="root">
<ul class="level-0 top-level">
<xsl:for-each select="*/nav">
<xsl:choose>
<xsl:when test="$page = '/index.aspx'">
<!-- level 0 -->
<li>
<a><xsl:attribute name="href"><xsl:value-of select="@path" /></xsl:attribute><xsl:value-of select="@name" /></a>
</li>
</xsl:when>
<xsl:when test="@path=$page and $page != '/index.aspx'">
<!-- level 2 -->
<li class="children-open current-menu-page">
<a><xsl:attribute name="href"><xsl:value-of select="@path" /></xsl:attribute><xsl:value-of select="@name" /></a>
<ul class="level-2 current-menu">
<xsl:for-each select="/root/menu/nav[@path=$page]/child::*">
<li>
<a><xsl:attribute name="href"><xsl:value-of select="@path" /></xsl:attribute><xsl:value-of select="@name" /><br /></a>
</li>
</xsl:for-each>
</ul>
</li>
</xsl:when>
<xsl:otherwise>
<li>
<a><xsl:attribute name="href"><xsl:value-of select="@path" /></xsl:attribute><xsl:value-of select="@name" /></a>
</li>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
XML文件看起来像这样:
<root name="menutest">
<menu>
<nav name="home" path="index.php" />
<nav name="menulink1" path="link1.php">
<nav name="menulink1child1" path="menulink1childlink1.php">
<nav name="menulink1child1child1"
path="menulink1childlink1childlink1.php" />
</nav>
</nav>
<nav name="menulink2" path="link2.php">
<nav name="menulink1child2" path="menulink2childlink2.php">
<nav name="menulink2child2child2"
path="menulink2childlink2childlink2.php" />
</nav>
</nav>
<nav name="menulink3" path="link3.php">
<nav name="menulink3child3" path="menulink3childlink3.php">
<nav name="menulink3child3child3"
path="menulink3childlink3childlink3.php" />
</nav>
</nav>
<nav name="menulink4" path="link4.php">
<nav name="menulink4child4"
path="menulink4childlink4.php">
<nav name="menulink4child4child4"
path="menulink4childlink4childlink4.php" />
</nav>
</nav>
</menu>
</root>
这基本上只显示基于参数“$ page”的第一层<nav>
个孩子。
菜单如何工作以及选择哪些节点的示例,基本对齐的<nav>
节点是子节点,缩进节点是父节点的子节点等等。xml example http://fraudo.orconhosting.net.nz/xml.png
TIA 贾里德
更新了代码段
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:param name="page" select="'index.aspx'"/>
<xsl:template name="makeUL">
<ul class="level-2 current-menu">
<xsl:apply-templates/>
</ul>
</xsl:template>
<xsl:template match="nav">
<li>
<xsl:if test=".//@path = $page and $page != '/index.aspx'">
<xsl:attribute name="class"><xsl:text>children-open current-menu-page</xsl:text></xsl:attribute>
</xsl:if>
<a href="{@path}">
<xsl:value-of select="@name" />
</a>
<xsl:if test=".//@path = $page and $page != '/index.aspx'">
<xsl:call-template name="makeUL"/>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>
我也在xml解析之前回显了“ul”,但我可能有错误:)。
echo '<ul class="level-0 top-level">'."\n\r";
echo $xsl->transformToXML($dom);
echo '</ul>'."\n\r";
答案 0 :(得分:2)
您遇到麻烦的根本原因是您正在尝试使用“拉”处理 - 传统结构,如xsl:for-each和xsl:choose,而不是使用模板规则和xsl:apply来编写“XSLT方式” -templates。通常可以用“拉”式编写代码,但专家会避免使用它,因为它往往会导致你遇到这种麻烦。
我说“通常”,但是一个不可能的情况是你的输入数据是递归的(nav元素中的nav元素,无限期嵌套)。您只能使用递归代码处理递归数据,在这种情况下,apply-templates编码风格变得至关重要。坐下来阅读教程并阅读一些示例,直到您理解了这个概念,然后在编码中使用它。
答案 1 :(得分:2)
如果要扩展包含已标识节点的树的分支,请使用以下样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:param name="page" select="'menulink1childlink1.php'"/>
<xsl:template match="menu" name="makeUL">
<ul>
<xsl:apply-templates/>
</ul>
</xsl:template>
<xsl:template match="nav">
<li>
<a href="{@path}">
<xsl:value-of select="@name" />
</a>
<xsl:if test=".//@path = $page">
<xsl:call-template name="makeUL"/>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>
输出:
<ul>
<li><a href="index.php">home</a></li>
<li><a href="link1.php">menulink1</a>
<ul>
<li><a href="menulink1childlink1.php">menulink1child1</a>
<ul>
<li><a href="menulink1childlink1childlink1.php"
>menulink1child1child1</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="link2.php">menulink2</a></li>
<li><a href="link3.php">menulink3</a></li>
<li><a href="link4.php">menulink4</a></li>
</ul>
渲染:
注意:这是.//
缩写可以使用的唯一情况。