获得不同节点的一个问题是如何确定两个节点是不同的。这是 XML 中的一个复杂主题。如果重复节点将具有相同的节点标识(即:它们引用相同的节点),那么您可以使用类似functx:distinct-nodes()的函数。否则,您需要某种类型的哈希来确定节点是否“足够”以被视为相等,或者使用 deep-equal() 进行比较,这对于大型数据集表现不佳。
如果姓氏和名字相同时两个<author>
s 相等,那么您可以使用像concat(last,first)
哈希这样简单的东西并使用 xpath 获得不同的值:
$xml/author[index-of($xml/author/concat(last,first), concat(last,first))[1]]
这仍然不理想,因为您在每一步都在计算哈希,因此对于大型数据集它会变慢。为了提高性能,您可以做的一件事是预先计算数据的哈希值,即:
<author hash="ShakespearWilliam">
<last>Shakespear</last>
<first>William</first>
</author>
和:
$xml/author[index-of($xml/author/@hash, @hash)[1]]
如果您可以通过哈希有效地获取有序节点(理想情况下使用有序数据库索引),那么有一种更有效的删除重复项的方法:
declare function local:nodupes($first, $rest)
{
if (empty($rest)) then $first
else if ($first/@hash eq $rest[1]/@hash)
then local:nodupes($rest[1], subsequence($rest,2))
else ($first, local:nodupes($rest[1], subsequence($rest,2)))
};
然后用你的有序集合调用它:
let $ordered :=
for $a in $xml/author
order by $a/@hash
return $a
return
local:nodupes((),$ordered)