如何在XQuery中获取不同的节点?

时间:2013-05-11 19:20:37

标签: xml xquery

将函数distinct-values()应用于节点序列时,它返回一系列值而不是一系列节点。

请有人向我解释一下XQuery数据模型的哪个特性使得难以直接在节点序列上消除重复值?

此外,如何将这一系列值转换回节点序列?

我查看了我的XML / XQuery笔记,并在没有找到明确信息的情况下搜索了互联网。

1 个答案:

答案 0 :(得分:4)

在XQuery中,每个节点都是不同的(它有一个内部唯一的节点ID)。


如果要比较节点,则必须深入比较它们的值。没有预定义的功能,但由于这是一个常见问题,FunctX包含一个functx:distinct-deep()。它依赖于functx:is-node-in-sequence-deep-equal(),所以你也需要它。

declare namespace functx = "http://www.functx.com";
declare function functx:distinct-deep 
  ( $nodes as node()* )  as node()* {

    for $seq in (1 to count($nodes))
    return $nodes[$seq][not(functx:is-node-in-sequence-deep-equal(
                          .,$nodes[position() < $seq]))]
 } ;
declare function functx:is-node-in-sequence-deep-equal 
  ( $node as node()? ,
    $seq as node()* )  as xs:boolean {

   some $nodeInSeq in $seq satisfies deep-equal($nodeInSeq,$node)
 } ;

或者你可以import the whole FunctX module,但这可能会减慢执行速度,具体取决于你的XQuery解释器。


如果你不想坚持使用FunctX,你需要搜索所有不同的值,并为每个找到第一个元素(所以没有任何前面的元素),并将data()与不同的值进行比较。

for $value in distinct-values(//data())
return //*[data() = $value][every $preceding in preceding::node() satisfies name() != $preceding/name()]

最后,这与上面的FunctX功能相同。您可以对某些部分使用其他构造,但不要忽略任何这些步骤。