如何在xpath中进行组捕获

时间:2012-07-07 04:03:18

标签: xpath

我在xpath中寻找的东西可以做://foo[@n="$1"]//bar[@n="$2"] 可以返回$1$2。或者至少给我<foo><bar>

这里有更多细节,我有一个xml文档:

<xml>
  <foo>
    <a n="1">
      <b n="1"/>
      <b n="2"/>
    </a>
  </foo>
  <a n="2">
    <b n="1"/>
  </a>
  <a n="3">
    <b n="1"/>
    <foo>
      <b n="2"/>
    </foo>
    <b n="3"/>
  </a>
</xml>

我希望在<a><b>的n属性上生成一个字符串 所以我有xpath://a[@n]//b[@n] 然后,对于我得到的每个结果,我使用:./@n./ancestor::a/@n来获取我想要的信息。

这很好用,但我需要更聪明的东西,因为我有很多这样的结构,需要自动生成xpath。

所以对于上面的例子,我正在寻找一些xpath,如://a[@n="$1"]//b[@n="$2"] 然后回复我: `(1,1),(1,2),(2,1),(3,1),(3,2),(3,3)

1 个答案:

答案 0 :(得分:3)

以下是一个XPath 1.0表达式,用于选择所有需要的n属性:

//a[.//b]/@n | //a//b/@n

如果没有优化,上述表达式的评估至少会执行两次XML文档的完整遍历。

此XPath 1.0表达式可能更有效

//*[self::a and .//b or self::b and ancestor::a]/@n

如果可以确保每个a都有b后代,则可以简化这两种表达式。

他们分别成为:

//a/@n | //a//b/@n

//*[self::a or self::b and ancestor::a]/@n

如果可以保证每个a都有一个后代b且每个b都有一个祖先a,则可以进一步简化。

//*[self::a or self::b]/@n

在单个XPath 1.0表达式中无法获取所有需要属性的字符串值。需要使用上述表达式之一获取所有属性,然后在每个选定的属性上应用第二个XPath表达式:string()

在Xpath 2.0中,可以使用单个表达式获取所需属性的所有字符串值 - 只需使用/string(.)附加每个表达式

例如,对于最简单的一个:

//(a|b)/@n/string(.)

<强>更新

OP已澄清他的问题。现在我们知道他希望产生这个结果:

(1, 1), (1, 2), (2, 1), (3, 1), (3, 2), (3, 3)

使用单个XPath 1.0表达式无法生成所需结果。

以下XPath 2.0表达式生成所需结果

for $a in //a[@n and .//b[@n]],
    $b in $a//b[@n]
  return
     concat('(', $a/@n, ',', $b/@n, ') ')