我正在尝试将xdmp:value与cts:包含在一个函数中,该函数传递给xdmp:value的值是动态的。我对函数式编程非常陌生,因此我的理解可能在这里有很大的缺陷。
这是一个有效的示例,将动态参数放置在cts:contains中,应澄清我的意图:
declare functional local:matchRegion($region as xs:string, $country as xs:string?)
as xs:boolean
{
let $in-country := '/country[name-variants/variant = $country]/regions/name-variants/variants'
let $anywhere := '/country/regions/region/name-variants/variant'
let $found := cts:contains(?, $region)
return
if ($country)
then ($found(xdmp:value($in-country)))
else ($found(xdmp:value($anywhere)))
};
local:matchRegion("ohio","usa") (: returns true :)
我正在尝试将对xdmp:value的调用预先加载。
这是我尝试过的:1)使用箭头运算符
declare functional local:matchRegion($region as xs:string, $country as xs:string?)
as xs:boolean
{
let $in-country := '/country[name-variants/variant = $country]/regions/name-variants/variants'
let $anywhere := '/country/regions/region/name-variants/variant'
let $found := xdmp:value(?) => cts:contains($region)
return
if ($country)
then ($found($in-country))
else ($found($anywhere))
};
local:matchRegion("ohio","usa") (: XDMP-XMLFUNC... Functions cannot be used in the content of an element constructor :)
2)使用简单的地图运算符:
declare functional local:matchRegion($region as xs:string, $country as xs:string?)
as xs:boolean
{
let $in-country := '/country[name-variants/variant = $country]/regions/name-variants/variants'
let $anywhere := '/country/regions/region/name-variants/variant'
let $found := xdmp:value(?) ! cts:contains(?,$region)
return
if ($country)
then ($found($in-country))
else ($found($anywhere))
};
local:matchRegion("ohio","usa") (: returns false :)
3)具有匿名功能:
declare functional local:matchRegion($region as xs:string, $country as xs:string?)
as xs:boolean
{
let $in-country := '/country[name-variants/variant = $country]/regions/name-variants/variants'
let $anywhere := '/country/regions/region/name-variants/variant'
let $a := function($x,$y){cts:contains(xdmp:value($x),$y)}
let $found := $a(?,$region)
return
if ($country)
then ($found($in-country))
else ($found($anywhere))
};
local:matchRegion("ohio","usa") (: returns false :)
我具有以与matchRegion类似的意图进行编写的功能,这将涉及更多的条件和更多的xpath表达式;我正在尝试利用动态调用来保持语法可读性和xdmp:value值,以避免对xpath进行不必要的评估。我怎样才能做到这一点?另外,为什么后两个实现返回false?最后,我认为cts:contains对我来说不会做任何特别的事情,因为我需要完全匹配。我对这一切还很陌生,所以请告诉我是否有更好的函数可以调用。
谢谢
更新:这是我要查询的xml文件的示例:
<country>
<name>Canada</name>
<name-variants>
<variant>canada</variant>
</name-variants>
<regions>
<region>
<name>Manitoba</name>
<name-variants>
<variant>manitoba</variant>
<variant>province of manitoba</variant>
</name-variants>
</region>
</regions>
</country>
你好,FaraBara:
请尝试下面的XQuery函数。
declare function local:matchOrNot( $region as xs:string,
$country as xs:string)
as xs:boolean
{
some $i in doc()/country/descendant-or-self::*[contains(., $country)]
satisfies $i/regions/region/descendant-or-self::*[contains(., $region)]
};
local:matchOrNot("new york", "usa");
您应该期望获得以下结果:
local:matchOrNot("new york", "usa"); => true
local:matchOrNot("new york", "USA"); => true
local:matchOrNot("New York", "USA"); => true
local:matchOrNot("New York", "usa"); => true
local:matchOrNot("New York", "Canada"); => false
Any combination of "New York" and "Canada" throws back "false"
您的XQuery函数包含多种语法和逻辑错误,因此,它们呈现错误的结果。