【问题标题】:xquery: how to get distinct values of nodesxquery:如何获取节点的不同值
【发布时间】:2012-09-23 11:26:20
【问题描述】:

我想知道 Xquery 是否有任何类似于 distinct-values 但返回节点的函数。

让我更清楚一点:例如,我有一个参考书目,对于其中的每个作者,我想列出他写的所有书籍。在我的具体案例中,作者元素是这样的:

<author>
  <last> Shakespear </last>
  <first> William </first>
</author>

在作者上使用 distinct-values 会返回 ShakespearWilliam,据我所知,它没有帮助。我想要一个保留元素作者结构而不考虑重复的函数。

如果您找到其他查询方式,请告诉我。有人知道吗?

【问题讨论】:

    标签: xml xquery distinct-values


    【解决方案1】:

    获取不同节点的一个问题是如何确定两个节点是否不同。这是 XML 中的一个复杂主题。如果重复节点将具有相同的节点标识(即:它们引用相同的节点),那么您可以使用类似functx:distinct-nodes() 的函数。否则,您需要某种类型的哈希来确定节点是否“足够”以被视为相等,或者使用 deep-equal() 进行比较,这对于大型数据集表现不佳。

    如果两个 &lt;author&gt;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)
    

    【讨论】:

    • 用于不同值的出色 xpath 表达式
    【解决方案2】:

    XQuery 3.0 有一个“分组依据”结构,例如,这允许您按(名字、姓氏)的值对作者进行分组。对节点进行分组后,您基本上就有了答案:当且仅当节点在不同的组中时,它们才是不同的。

    周围有很多产品实现了 XQuery 3.0 草案的这一部分; Saxon 9.4 就是其中之一。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多