【发布时间】:2010-12-11 22:58:52
【问题描述】:
我想存储当前节点的路径,以便在 XSLT 的表达式中重用它。有可能吗?
<!-- . into $path? -->
<xsl:value-of select="$path" />
【问题讨论】:
-
好问题,+1。请参阅我的答案以获得解释以及替代、更简单和现实的解决方案。
我想存储当前节点的路径,以便在 XSLT 的表达式中重用它。有可能吗?
<!-- . into $path? -->
<xsl:value-of select="$path" />
【问题讨论】:
你好,我想存储路径 当前节点,以便我可以重用它 XSLT 中的表达式。有可能吗?
任何给定节点都可以构造一个 XPath 表达式,在计算时,该表达式恰好选择该节点。事实上,存在不止一个选择同一个节点的 XPath 表达式。
有关构造此类 XPath 表达式的确切 XSLT 代码,请参阅 this answer。
问题是这个 XPath 表达式不能在 XSLT 1.0 或 XSLT 2.0 中的同一转换期间计算,除非使用 EXSLT 扩展函数 dyn:evaluate(并且很少有 XSLT 1.0 处理器实现 dyn :evaluate())。
可以使用<xsl:variable> 指令在 XSLT 中以更简单的方式实现您想要的目标:
<xsl:variable name="theNode" select="."/>
此变量可以在其范围内的任何位置引用为$theNode,,并且可以在应用或调用模板时作为参数传递。
【讨论】:
不,这在 vanilla XSLT 1.0 中是不可能的。没有简单的方法来检索给定节点的 XPath 表达式字符串,而且绝对没有办法评估 看起来像 XPath 就像是 XPath 的字符串。
有一些扩展支持 XPath 表达式的动态求值,但这些扩展并不与每个 XSLT 处理器兼容。
无论如何,如果您提供更多关于您实际尝试做的事情的详细信息,则可能有另一种方法可以做到。
【讨论】:
正如@Dimitre 和@Tomalak 所指出的,我认为在同一个转换中获取表示给定节点的XPath 表达式的字符串,然后选择节点“解析”这样的字符串。我可以看到执行这些操作的一些价值在不同的转换。
除此之外,这个样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:for-each select=".|//node()|//@*">
<xsl:variable name="vPath">
<xsl:apply-templates select="." mode="getPath"/>
</xsl:variable>
<xsl:value-of select="concat($vPath,'
')"/>
<xsl:call-template name="select">
<xsl:with-param name="pPath" select="$vPath"/>
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template match="/|node()|@*" mode="getPath" name="getPath">
<xsl:apply-templates select="parent::*" mode="getPath"/>
<xsl:text>/</xsl:text>
<xsl:choose>
<xsl:when test="self::*">
<xsl:value-of select="concat(name(),'[',
count(preceding-sibling::*
[name() =
name(current())]) + 1,
']')"/>
</xsl:when>
<xsl:when test="count(.|../@*)=count(../@*)">
<xsl:value-of select="concat('@',name())"/>
</xsl:when>
<xsl:when test="self::text()">
<xsl:value-of
select="concat('text()[',
count(preceding-sibling::text()) + 1,
']')"/>
</xsl:when>
<xsl:when test="self::comment()">
<xsl:value-of
select="concat('comment()[',
count(preceding-sibling::comment()) + 1,
']')"/>
</xsl:when>
<xsl:when test="self::processing-instruction()">
<xsl:value-of
select="concat('processing-instruction()[',
count(preceding-sibling::
processing-instruction()) + 1,
']')"/>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="select">
<xsl:param name="pPath"/>
<xsl:param name="pContext" select="/"/>
<xsl:param name="pInstruction" select="'value-of'"/>
<xsl:variable name="vPosition"
select="number(
substring-before(
substring-after($pPath,
'['),
']'))"/>
<xsl:variable name="vTest"
select="substring-before(
substring-after($pPath,
'/'),
'[')"/>
<xsl:variable name="vPath" select="substring-after($pPath,']')"/>
<xsl:choose>
<xsl:when test="$vPath">
<xsl:call-template name="select">
<xsl:with-param name="pPath" select="$vPath"/>
<xsl:with-param name="pContext"
select="$pContext/*[name()=$vTest]
[$vPosition]"/>
<xsl:with-param name="pInstruction"
select="$pInstruction"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vContext"
select="$pContext/node()
[self::*[name()=$vTest]|
self::comment()[$vTest='comment()']|
self::text()[$vTest='text()']|
self::processing-instruction()
[$vTest =
'processing-instruction()']]
[$vPosition]|
$pContext[$pPath='/']|
$pContext/@*[name() =
substring($pPath,3)]
[not($vTest)]"/>
<xsl:choose>
<xsl:when test="$pInstruction='value-of'">
<xsl:value-of select="$vContext"/>
</xsl:when>
<xsl:when test="$pInstruction='copy-of'">
<xsl:copy-of select="$vContext"/>
</xsl:when>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
有了这个输入:
<?somePI pseudoAttributes?>
<root>
<!-- This is a comment -->
<node attribute="Value">text</node>
</root>
输出:
/
text
/processing-instruction()[1]
pseudoAttributes
/root[1]
text
/root[1]/comment()[1]
This is a comment
/root[1]/node[1]
text
/root[1]/node[1]/@attribute
Value
/root[1]/node[1]/text()[1]
text
【讨论】: