我不确定我是否理解"轴"。
"轴定义相对于当前节点的节点集。" (http://www.w3schools.com/xsl/xpath_axes.asp)。 self
选择当前节点。 "。"还选择当前节点。
self
axis 包含上下文节点本身。自轴可以缩写为单个句点(。)。表达式self::*
和。是等价的。 (http://docstore.mik.ua/orelly/xml/xslt/ch03_02.htm)
因此,//*
选择所有节点,//*[self::td]
将其限制为树中当前节点下的td
个节点。这听起来与.//td
相同。但它不是。
<!DOCTYPE html>
<html>
<head>
<title>Not this</title>
</head>
<body>
<table>
<tbody>
<tr>
<td>
<span>
<a>This is the title we want</a>
</span>
</td>
</tr>
</tbody>
</table>
<p><span class="c2">not this.</span></p>
<p><span class="c2">not this</span></p>
<table>
<tbody>
<tr>
<td width="235"><span class="c2">not this.</span></td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
</tr>
<tr>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
</tr>
<tr>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
</tr>
<tr>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
</tr>
<tr>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
<td class="c5"><span class="c4">not this</span></td>
</tr>
</tbody>
</table>
</body>
</html>
所以如果我运行这个XSLT,
<xsl:template match="body">
<xsl:element name="chapter">
<xsl:element name="title">
<xsl:value-of select="( //*[self::td])[1]" />
</xsl:element>
</xsl:element>
</xsl:template>
然后我得到:
<chapter>
<title>This is the title we want</title>
</chapter>
但如果我们跑:
<xsl:template match="body">
<xsl:element name="chapter">
<xsl:element name="title">
<xsl:value-of select=".//td[1]"/>
</xsl:element>
</xsl:element>
</xsl:template>
然后我们得到:
<chapter>
<title>This is the title we want not this. not this not this not this not this not this</title>
</chapter>
这很奇怪。我原本以为这两个应该是等价的。
<xsl:value-of select=".//p[1]"/>
返回每个p元素的值。
<xsl:value-of select="( //*[self::p])[1]" />
仅返回第一个p元素的内容。
为什么?
答案 0 :(得分:1)
首先,这两个不等效:
.//p
选择作为当前节点后代的每个p
。
//p
选择作为根节点后代的每个p
- 即整个文档中的每个p
。
接下来,这个:
<xsl:value-of select=".//td[1]"/>
选择所有后代td
元素,这些元素是其父的第一个td
子(参见:http://www.w3.org/TR/xpath/#path-abbrev)。
OTOH,这:
<xsl:value-of select="( //*[self::td])[1]" />
选择整个文档中所有td
元素中的第一个元素。它可以更简单地写成:
<xsl:value-of select="(//td)[1]" />