我可以在XSLT中动态构建此XPath查询吗?

时间:2010-03-21 06:18:25

标签: xml xslt xpath

我有一个类似于

的文档
<root>
    <element>
        <subelement1 />
        <subelement2 />
    </element>
    <element>
        <subelement2 />
        <subelement1 />
    </element>
</root>

/element[2]/[someNode]上下文中的我的XSLT表中,我希望得到一个代表/element[1]/[someNode]距离的数字(即/element1/[someNode]的前一个兄弟的数量)。例如,在/element[2]/subelement1的上下文中,我想要一些方法来获取数字2,即从/element[1]/element[1]/subelement2的距离。我只需要<element>的第一个实例中给定节点名称的距离。

直觉我觉得我可以像

那样构建它
 <xsl:variable name="nodename" select="name()" />
 <xsl:value-of select="/element[1]/$nodename/preceding-sibling::*" />

但不幸的是这张表没有编译。我正在尝试在XSLT中实现什么?

3 个答案:

答案 0 :(得分:8)

  1. 您不能将XSLT变量用作XPATH语句的轴,但可以在谓词过滤器中使用它。因此,如果要匹配任何元素(即*),然后将其限制为名称()等于存储在变量中的值(即*[name()=$nodename])的元素,则XPATH将有效

  2. 您构建的XPATH将返回匹配元素的值。如果要返回与该模式匹配的元素数,可以使用count()函数。

  3. 您的示例XML有一个文档元素<root>,但您的XPATH不包含<root>

  4. 这将使用上下文节点指定的变量返回previous-sibling元素的数量:

    <xsl:variable name="nodename" select="name()" />
    <xsl:value-of select="count(/root/element[1]/*[name()=$nodename]/preceding-sibling::*)" />
    

    您可以删除变量,只需使用:

    <xsl:value-of select="count(/root/element[1]/*[name()=name(current())]/preceding-sibling::*)" />
    

答案 1 :(得分:1)

*[name() = $nodename]可能是您想要的而不是$nodename,但您应该更好地使用local-name()和namespace-uri()的值定义两个变量,并检查例如*[local-name() = $localname and namespace-uri() = $namespaceuri]具有选择元素的命名空间安全方式。

答案 2 :(得分:0)

很遗憾,构建xpath是不可能的。 XPath是静态编译的;你不能动态生成它们(或者如果你这样做,它们只是字符串而且不能被执行)。

然而,你可以做的是写一个恰好交叉引用几个本身是动态的值的查询......