我需要一个XSLT函数,它会将xpath返回给它调用的节点。
<root>
<node>
<subnode />
<subnode />
<subnode />
</node>
<node>
<subnode>
<subsubnode >
<xsl:value-of select="fn:generateXPath()" />
</subsubnode >
</subnode>
</node>
</root>
<xsl:template match="root/node/subnode/sub" >
<xsl:value-of select="fn:generateXPath()" />
</xsl:template>
<xsl:function name="fn:generateXPath" >
<xsl:for-each select="ancestor::*">
<xsl:value-of select="name()" />
</xsl:for-each>
<xsl:value-of select="name()" />
</xsl:function>
我尝试使用上面的函数,但它会抛出一个错误:
XPDY0002:无法在此处选择节点:上下文项未定义
但是当我在命名模板中尝试这个时,我能够得到结果。可以使用xslt:function
实现这一点。
答案 0 :(得分:4)
我尝试使用上面的函数,但它会抛出一个错误:
XPDY0002: Cannot select a node here: the context item is undefined
但是当我在命名模板中尝试这个时,我能够得到它 结果
根据W3C XSLT 2.0规范:
“在样式表函数的主体内,最初的重点是 不确定的;这意味着任何引用上下文项的尝试, 上下文位置或上下文大小是不可恢复的动态错误。 [XPDY0002]“
在您的代码中:
<xsl:function name="fn:generateXPath" >
<xsl:for-each select="ancestor::*">
<xsl:value-of select="name()" />
</xsl:for-each>
<xsl:value-of select="name()" />
</xsl:function>
有许多相对表达式只能针对上下文项(焦点,当前节点)进行评估,但是根据定义没有这样的定义(参见上面的引文),因此你得到报告的错误。
<强>解决方案强>:
为此函数添加一个参数 - 自然,这将是节点,用于选择所需的XPath:
<xsl:function name="fn:generateXPath" as="xs:string" >
<xsl:param name="pNode" as="node()"/>
<xsl:for-each select="$pNode/ancestor::*">
<xsl:value-of select="name()" />
</xsl:for-each>
<xsl:value-of select="name($pNode)" />
</xsl:function>
并按以下方式调用此函数:
fn:generateXPath(someNode)
注意:显然,您必须将每个名称连接到"/"
字符,并通过使用谓词中的位置缩小表达式,以便不选择节点的任何兄弟节点。有关为节点构建XPath表达式的完整且正确的解决方案,请参阅我对此问题的回答: https://stackoverflow.com/a/4747858/36305
答案 1 :(得分:3)
没有标准功能的一个原因是人们出于不同的原因想要路径:
有时a/b/c/d
就足够了。
有些人想要a[3]/b[5]/c[1]/d[2]
。
有些人想要一个名称不包含名称空间前缀的路径,所以它必须类似
*:a[namespace-uri()='abc']/*:b[namespace-uri='xyz']
等。