【问题标题】:XSLT function to get xpath to a nodeXSLT 函数获取节点的 xpath
【发布时间】:2012-01-20 04:09:54
【问题描述】:

我需要一个 XSLT 函数,它将返回我调用它的节点的 xpath。

XML

    <root>
      <node>
        <subnode />
        <subnode />
        <subnode />
      </node>
      <node>
        <subnode>
          <subsubnode >
            <xsl:value-of select="fn:generateXPath()" />
          </subsubnode >
        </subnode>
      </node>
    </root>

XSL

    <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 来实现吗?

【问题讨论】:

    标签: xslt xpath xmlnode


    【解决方案1】:

    我尝试了上面的函数,但它抛出了一个错误:

    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>    
    

    有许多 relative 表达式只能针对上下文项(焦点,当前节点)进行评估,但是定义中没有这样定义(参见上面的引用),因此您获取报告的错误。

    解决方案

    为这个函数添加一个参数——很自然,这将是节点,用于选择所需的 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

    【讨论】:

    • 还要注意有用的缩写&lt;xsl:value-of select="$pNode/ancestor::*/name()" separator="/"/&gt;
    • @MichaelKay:是的,我会那样做。在这里,我只是添加了必要的更改,而不是深入研究 OP 的代码。
    • 我将返回值分配给一个变量。我需要从另一个相同模式的 XML 中获取值。为此我尝试过, 。但这给了我一个错误,XPTY0004: A sequence of multiple item is not allowed as the first argument of saxon:evaluate().
    【解决方案2】:

    没有标准功能的一个原因是人们出于不同的原因想要路径:

    有时a/b/c/d 就足够了。

    有些人想要a[3]/b[5]/c[1]/d[2]

    有些人想要一个名称不包含命名空间前缀的路径,所以它必须类似于

    *:a[namespace-uri()='abc']/*:b[namespace-uri='xyz']

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-30
      • 2018-04-18
      • 2011-01-19
      • 1970-01-01
      • 2011-02-09
      • 2015-03-30
      • 2023-03-27
      相关资源
      最近更新 更多