如何使用XSLT根据标准匹配获取位置?

时间:2011-11-09 10:42:43

标签: xml xslt xpath

这是我的XML:

<summary>
<test>
   <name>test1</name>
   <status>failure</status>
</test>
<test>
   <name>test2</name>
   <status>success</status>
</test>
<test>
   <name>test3</name>
   <status>success</status>
</test>
</summary>

如果&lt; status&gt;是成功,我需要存储&lt; test&gt;的position()变量中的节点并从下一个模板中获取它。我只需要第一场比赛的位置()。这可能吗?

2 个答案:

答案 0 :(得分:2)

我建议使用包含所需位置的全局变量

 <xsl:variable name="vFirstPassedPosition" select=
     "count(/*/test
                [status='success'][1]
                   /preceding-sibling::test) +1"/>

因为此变量是全局变量(<xsl:stylesheet>的子项),所以可以从任何模板引用它而无需在模板中重新计算:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:variable name="vFirstPassedPosition" select=
 "count(/*/test
           [status='success'][1]
                  /preceding-sibling::test) +1"/>

 <xsl:template match="/">
     <xsl:value-of select="$vFirstPassedPosition"/>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此示例转换时

<summary>
    <test>
        <name>test1</name>
        <status>failure</status>
    </test>
    <test>
        <name>test2</name>
        <status>success</status>
    </test>
    <test>
        <name>test3</name>
        <status>success</status>
    </test>
</summary>

从任何模板中访问该位置(在本例中我们只有一个模板)并正确输出

2

如果XML文档的结构未知/不可预测,并且可以具有任何级别的嵌套,包括嵌套的test元素,则使用:

 <xsl:variable name="vFirstPassedPosition" select=
  "count((//test[status='success'])[1]
                  /preceding::test)
  +
   count((//test[status='success'])[1]
                  /ancestor::test)

   +1"/>

请注意:使用以下表达式来查找第一个test元素,其status子元素的字符串值为{{1} }:

"success"
  1. 在您的情况下,根本不需要//test[status='success'][1] 伪运算符,因为XML文档的结构是静态已知的,并且可以使用更高效的XPath表达式。

  2. //通常可以选择多个元素。它选择任何//test[status='success'][1]元素,其test子元素的字符串值为status,并且是其父元素的第一个子元素。这是XPath中最常见的FAQ之一。 记住:XPath "success"运算符的优先级(优先级)高于[]伪运算符。如果您确实必须使用//(例如,事先不知道XML文档的确切结构),那么选择第一个这样的元素的正确XPath是:

  3. //

    与许多其他编程语言(通常在数学中)一样,括号用于显式覆盖标准运算符的优先级。

答案 1 :(得分:0)

  

我需要将节点的position()存储在变量和fetch中   它来自下一个模板。

“下一个模板”在XSLT中没有任何意义。未指定模板以特定顺序执行。 XSLT是声明性的而不是程序性的。也许您的意思是应用于以下<test>元素的模板。

由于模板应用的这种未指定顺序,在应用一个模板期间存储某些内容并在应用另一个模板期间检索它是没有意义的,因为您可能最终会在存储之前尝试检索它它

从声明的角度思考时,解决方案是:

  • 如果应用于元素X的模板需要有关元素Y的数据,而不是依赖于当前上下文的 ,则只需使用全局变量并计算一次数据。这就是你正在看的情况(因为你只需要通过的第一个测试),这就是@Dimitre给你答案的情况。

  • 如果应用于元素X的模板需要有关元素Y的数据,而 依赖于当前上下文,则计算需要它的模板中的值(模板处理元素X) ,而不是在处理元素Y的模板中。