Xquery-如何匹配量词表达式中的两个序列
和许多人一样,我正在处理基于XML的Mondial数据库。如果XQuery语法没有尽力破坏,那将是小菜一碟Xquery-如何匹配量词表达式中的两个序列,xquery,contains,Xquery,Contains,和许多人一样,我正在处理基于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
$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/所在地/省份示例@
province="prov-France-5 prov-France-20 prov-France-89 prov-France-99"
//province/@id示例
id="prov-Greece-2"
XQuery有多种不同于您预期的工作方式
=
和=如果至少有一个参数是序列而不是单个项,则代码>具有存在语义。这意味着$seq1=$seq2
相当于某些$seq1中的$x,$seq2中的$y满足$x=$y
。查询('foo','bar')=('bar','baz','quoz')
返回true
,因为至少有一个公共项
//province/@id
的XQuery异常计算为所有匹配节点的序列。在您的情况下,这将是一个超过1000个省id的序列:(id=“prov-cid-cia-greese-2”,id=“prov-cid-cia-greese-3”,id=“prov-cid-cia-greese-4”,[…])
。然后将此序列绑定到let
子句中的变量$inland
。由于您不迭代$INLAIN
中的单个项目(例如,使用for
子句),因此where
条件将立即对全球所有省份的整个序列起作用。所以你的条件在//sea中每$sea满足
$sea/位于/@省!=$内陆现在的意思是:
“对于每个sea
都有一个省
位于其旁边,其@id
至少不等于所有现有省id中的一个。”
这将返回false
,因为有sea
s没有子对象,例如亚丁湾
contains($str,$sub)
不适合检查子字符串是否包含在空格分隔的字符串中,因为它还匹配部分条目:contains(“foobar baz qux”,“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
s旁边的所有(唯一)省份,然后返回不按该顺序排列的所有省份:
let $next-to-sea := distinct-values(//sea/located/@province/tokenize(.))
return //province/@id[not(. = $next-to-sea)]
更紧凑(但可能效率更低):
另一方面,您可以使用XQuery 3.0地图,通过一次查找来替代所有海滨省份的潜在线性搜索:
let $seaside :=
map:merge(
for $id in //sea/located/@province/tokenize(.)
return map{ $id: () }
)
return //province/@id[not(map:contains($seaside, .))]
不确定这是您当前的错误,但XQuery必须返回格式良好的XML,而格式良好的XML序列不是(没有根标记);请尝试
return{$inland}
maybe?它在contains函数中的逗号处特别出错。谢谢你的建议。对,contains是一个字符串函数,它需要一个字符串和一个潜在的子字符串,而不是一个序列和一个潜在的元素。应该会有帮助。我知道他们在那里做了什么@Aaron,但这还不够,我需要能够与一个子串匹配,例如一个名为“province2”的省和一个与“province2 province4”接壤的海洋。非常感谢!这同时回答了很多问题,很好的信息:)
let $seaside :=
map:merge(
for $id in //sea/located/@province/tokenize(.)
return map{ $id: () }
)
return //province/@id[not(map:contains($seaside, .))]