我有以下 xml 站点地图文件:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="NewSiteMap.xsl"?>
<siteMap>
<siteMapNode
url="~/UsingMasterTemplate.aspx?id=1"
title="Home"
description="AAAAAAAAAAAAAAAAAAA">
<siteMapNode
url="~/UsingMasterTemplate.aspx?id=2"
title="Profile"
description="BBBBBBBBBBBBBBBBBB" />
<siteMapNode
url="~/UsingMasterTemplate.aspx?id=3"
title="People"
description="CCCCCCCCCCCCCCCCCCCCCCCC" />
<siteMapNode
url="~/UsingMasterTemplate.aspx?id=5"
title="New Page"
description="DDDDDDDDDDDDDDDDDDDD" />
</siteMapNode>
</siteMap>
下面的xsl文件进行递归并输出到ul:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method='xml' version='1.0' omit-xml-declaration="yes" encoding='UTF-8' indent='yes'/>
<xsl:template match="siteMap">
<!--
<xsl:variable name='siteMapNode'>
<xsl:value-of select='siteMap/siteMapNode'/>
</xsl:variable>
-->
<html>
<head>
<link rel="stylesheet" href="xSiteMap.css" type="text/css" />
</head>
<body>
<h2>SiteMap:</h2>
<ul>
<!-- Check for empty sitemap -->
<xsl:if test='siteMapNode'>
<xsl:call-template name='BuildNavList'>
<xsl:with-param name='siteMapNode' select='siteMapNode'/>
</xsl:call-template>
</xsl:if>
</ul>
</body>
</html>
</xsl:template>
<xsl:template name='BuildNavList'>
<xsl:param name='siteMapNode'/>
<li>
<a>
<xsl:attribute name="href">
<xsl:value-of select="$siteMapNode/@url"/>
</xsl:attribute>
<xsl:attribute name="title">
<xsl:value-of select="$siteMapNode/@description"/>
</xsl:attribute>
<xsl:value-of select="$siteMapNode/@title"/>
</a>
<!-- test for node-children, if true then recursion -->
<xsl:if test='$siteMapNode/node()'>
<ul>
<xsl:for-each select="$siteMapNode/node()">
<xsl:call-template name='BuildNavList'>
<xsl:with-param name='siteMapNode' select='$siteMapNode/node()'/>
</xsl:call-template>
</xsl:for-each>
</ul>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>
但是我的递归调用中似乎存在错误(可能是我的 for-each 语句中的轴错误)!这里出了什么问题?
最佳答案
除了 Gaby 的回答之外,您可能还想知道使用 call-template 并传递一个参数(节点)只是将模板应用于该节点的一种迂回方式(没有模板匹配)。 Apply-templates 是完成您正在做的事情的正常 XSLT 方式,而且它不那么冗长。
所以你的初始调用模板
<xsl:if test='siteMapNode'>
<xsl:call-template name='BuildNavList'>
<xsl:with-param name='siteMapNode' select='siteMapNode'/>
</xsl:call-template>
</xsl:if>
可以成为
<xsl:apply-templates select='siteMapNode'/>
这将应用于名为 siteMapNode 的上下文节点的子节点。
然后你的递归模板就变成了
<xsl:template match="siteMapNode">
<li>
<a href="{@url}" title="{@description}">
<xsl:value-of select="@title"/>
</a>
<!-- test for siteMapNode element children, if true then recur -->
<xsl:if test='siteMapNode'>
<ul>
<xsl:apply-templates select="siteMapNode" />
</ul>
</xsl:if>
</li>
</xsl:template>
请注意,我们消除了对 $siteMapNode 参数的大量引用,因为它现在是上下文节点。另请注意 <a href=""
使用的属性值模板和title="">
。更加简洁和可读!
当您按照设计方式理解和使用 XSLT 时,它确实会更方便!
关于xml - XSL递归轴故障?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4067719/