gpt4 book ai didi

Xquery - 如何匹配量词表达式中的两个序列

转载 作者:行者123 更新时间:2023-12-02 00:36:18 25 4
gpt4 key购买 nike

与许多人一样,我正在处理基于 XML 的 Mondial 数据库。如果 XQuery 语法没有尽最大努力进行破坏,那将是小菜一碟。

let $inland := //province/@id
where every $sea in //sea satisfies
$sea/located/@province != $inland
return $inland

我在上面试图做的是找到所有“内陆”省份,即没有旁边有海的省份。然而,这是行不通的,因为 $sea/located/province 是一个大字符串,与它接壤的每个省都在其中。

于是我尝试修改成。

let $inland := //province/@id
where every $sea in //sea satisfies
not(contains($sea/located/@province, $inland))
return $inland

我希望它只找到属于海洋边界省份的省份。简单明了。

错误信息:

Stopped at C:/Users/saffekaffe/Desktop/mondial/xml/country_without_island.xml, 2/1:
[XPTY0004] Item expected, sequence found: (attribute id {"prov-Greece-2"},....

我该如何解决这个问题?

示例//sea/located/province@

province="prov-France-5 prov-France-20 prov-France-89 prov-France-99" 

//province/@id 的例子

id="prov-Greece-2"

最佳答案

XQuery 有多种工作方式,与您的预期不同。

  1. 比较运算符 =!= 具有存在语义 如果它们的至少一个参数是序列 而不是单个项目。这意味着$seq1 = $seq2等价于$seq1中的$x,$seq2中的$y满足$x = $y。查询 ('foo', 'bar') = ('bar', 'baz', 'quuz') 返回 true 因为至少有一个共同项。

  2. //province/@id 这样的 XQuery 异常计算所有匹配节点的序列。在您的情况下,这将是 1000 多个省 ID 的序列:(id="prov-cid-cia-Greece-2", id="prov-cid-cia-Greece-3", id="prov -cid-cia-Greece-4", [...])。然后将该序列绑定(bind)到 let 子句中的变量 $inland。由于您没有遍历 $inland 中的单个项目(例如使用 for 子句),因此 where 条件适用于整体全局所有省份的序列一次。所以你的条件 every $sea in//sea 满足
    $sea/located/@province != $inland
    现在意味着:
    “对于每个,它旁边都有一个,它的@id不等于至少一个所有现有的省份 ID。”
    这返回 false,因为有 sea 没有 located child ,例如 Gulf of Aden。 p>

  3. contains($str, $sub) 不适合检查子字符串是否包含在以空格分隔的字符串中,因为它也匹配部分条目:contains("foobar baz quux", "oob") 返回 true
    相反,您应该使用 tokenize($str) 将字符串分成多个部分并查看其各个部分,或者使用 contains-token($str, $token)

综合起来,一个与您原来的查询非常相似的正确查询是:

for $inland in //province/@id
where
every $sea in //sea
satisfies not(contains-token($sea/located/@province, $inland))
return $inland

另一种方法是首先收集 sea 旁边的所有(唯一)省份,然后返回所有不在该顺序中的省份:

let $next-to-sea := distinct-values(//sea/located/@province/tokenize(.))
return //province/@id[not(. = $next-to-sea)]

更紧凑(但可能效率较低):

//province/@id[not(. = //sea/located/@province/tokenize(.))]

在频谱的另一端,您可以使用 XQuery 3.0 map 通过一次查找来取代对所有沿海省份的潜在线性搜索:

let $seaside :=
map:merge(
for $id in //sea/located/@province/tokenize(.)
return map{ $id: () }
)
return //province/@id[not(map:contains($seaside, .))]

关于Xquery - 如何匹配量词表达式中的两个序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49390355/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com