设置当前节点以进行XPath评估

时间:2012-07-12 13:33:55

标签: java xslt xpath xalan jaxp

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

position()=last()-1

javax.xml.xpath包含:

  

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

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

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

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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)足够吗?

答案 2 :(得分:0)

This post from 7 years ago建议可以使用Xalan特定的非XSLT解决方案,但实现独立性和迈克尔的响应促使我朝着寻找基于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:评估(感谢Martin!)
  2. $ pos,用于标识我想要的当前节点。
  3. 我能够使用Dimitre's answer计算$ pos到之前的问题;我还使用了他的变量名vNodeSet

    感谢Dimitre,Martin和Michael!