3

我正在寻找 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>

我想根据 in 的 n 属性生成一个字符串<a><b> 所以我有 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)

4

1 回答 1

4

这是一个选择所有需要的n属性的 XPath 1.0 表达式:

//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, ') ')
于 2012-07-07T15:39:39.347 回答