【问题标题】:Setting current node for XPath evaluation为 XPath 评估设置当前节点
【发布时间】:2012-07-12 06:30:42
【问题描述】:

给定一个节点列表和该列表中的当前节点,有没有一种方法可以使用 javax.xml.xpath(或 org.apache.xpath)来评估位置相关的 XPath 表达式,例如:

position()=last()-1

javax.xml.xpath 包含:

评估(字符串表达式,对象项,QName returnType) 在指定的上下文中计算 XPath 表达式并将结果作为指定的类型返回。

我想我可以创建一个临时节点,将节点列表中的节点添加为子节点,并将与当前节点对应的子节点作为上下文进行评估,但是(假设甚至可以)有更好的方法吗?

或者,在 XSLT 1.0 中,假设我将这三个东西(节点列表、节点和 xpath 表达式(作为字符串))作为变量。是否可以将此表达式应用于节点,使用节点列表作为上下文,并将结果作为变量获取?

【问题讨论】:

    标签: java xslt xpath xalan jaxp


    【解决方案1】:

    大多数 XPath API,当然还有 JAXP API,只允许您设置单例焦点,即您可以选择任何项目作为上下文项目的焦点,但上下文位置和大小固定为 1。

    【讨论】:

      【解决方案2】:

      Xalan Java 支持http://www.exslt.org/dyn/functions/evaluate/index.html,因此您应该能够使用例如

      <xsl:variable name="nodes" select="/root/foo/bar"/>
      <xsl:variable name="expression" select="concat('$nodes/', $yourPath)"/>
      <xsl:variable name="result" select="dyn:evaluate($expression)"/>
      

      (当然定义了xmlns:dyn="http://exslt.org/dynamic")。

      这有帮助吗?我不确定我是否理解拥有节点列表和单个节点并希望将两者用作上下文的部分。

      至于 Java 端,在 DOM NodeList 中找到最后一个节点之前的节点,nodeList.getItem(nodeList.getLength() - 2) 不应该足够吗?

      【讨论】:

        【解决方案3】:

        This post from 7 years ago 建议可能有一个特定于 Xalan 的非 XSLT 解决方案,但实现独立性和 Michael 的回应促使我朝着寻找基于 XSLT1 的有效解决方案的方向前进。

        在这里;我不确定它是否对其他人有用。不知道有没有更简单的方法?

        只要您正确设置了所有内容,您就可以依赖 XSLT。来自规范:

        在 XSLT 中,一个最外层的表达式(即不是一部分的表达式 的另一个表达式)获取其上下文如下:

        上下文节点来自当前节点

        上下文位置来自当前节点在 当前节点列表;第一个位置是 1

        从最后开始,我得到将表达式 $expression 应用于变量 $result 的结果:

                <xsl:variable name="result" >
                    <xsl:apply-templates select="$vNodeSet" mode="myeval">
                        <xsl:with-param name="expression" ><xsl:value-of select="$expression"/></xsl:with-param>
                        <xsl:with-param name="pos" ><xsl:value-of select="$pos"/></xsl:with-param>
                    </xsl:apply-templates>
                </xsl:variable> 
        

        apply-templates 将一个合适的“当前节点列表”推送到以下模板:

          <xsl:template match="*" mode="myeval">
            <xsl:param name="expression">1. </xsl:param>
            <xsl:param name="pos">3</xsl:param>
        
            <xsl:choose>
                <xsl:when test="position()=$pos">
                    <xsl:value-of select="dyn:evaluate($expression)" /></xsl:when>
                <xsl:otherwise /> 
            </xsl:choose>
        
          </xsl:template>
        

        此模板评估我想成为“当前节点”的节点的表达式。注意:

        1. dy:evaluate 的使用(感谢 Martin!)
        2. $pos 标识我想要的当前节点。

        我能够使用 Dimitre's answer 计算 $pos 到较早的问题;我也用过他的变量名 vNodeSet

        感谢 Dimitre、Martin 和 Michael!

        【讨论】:

        • Jason,一些 cmets:而不是 &lt;xsl:with-param name="expression" &gt;&lt;xsl:value-of select="$expression"/&gt;&lt;/xsl:with-param&gt;,只需使用 &lt;xsl:with-param name="expression" select="$expression"/&gt;,这样写起来更短,效率更高。同样的方法可以用于第二个xsl:with-param。而且我认为,如果您只想将dyn:evaluate 应用于节点集中的某个节点,您只需要&lt;xsl:apply-templates select="$vNodeSet[position() = $pos]" mode="myeval"&gt; 加上&lt;xsl:template match="*" mode="myeval"&gt;&lt;xsl:value-of select="dyn:evaluate($expression)" /&gt;&lt;/xsl:template&gt;
        • 谢谢马丁。我想我首先尝试了 ,但这不起作用(使用 Xalan),尽管我可能弄错了。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多