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

-2 xml xquery

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

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

另外,如何将这个值序列转回节点序列?

我浏览了 XML/XQuery 笔记并搜索了互联网,但没有找到明确的信息。

Jen*_*rat 5

在 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)
 } ;
Run Code Online (Sandbox Code Playgroud)

或者,您可以导入整个 FunctX 模块,但这可能会大大减慢执行速度,具体取决于您的 XQuery 解释器。


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

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

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