Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在XQuery中从交叉点排除空列表_Xquery - Fatal编程技术网

在XQuery中从交叉点排除空列表

在XQuery中从交叉点排除空列表,xquery,Xquery,我有几个清单,可能是空的,也可能不是空的。我想找到所有列表中出现的元素,但只针对那些不是空的列表。 我有这样的想法: let $results := $list1 intersect $list2 intersect $list3 intersect $list4 let $results := local:safe-intersect( $list1, local:safe-intersect( $l

我有几个清单,可能是空的,也可能不是空的。我想找到所有列表中出现的元素,但只针对那些不是空的列表。 我有这样的想法:

let $results := 
    $list1 intersect  
    $list2 intersect 
    $list3 intersect 
    $list4
let $results := 
    local:safe-intersect(
      $list1,
      local:safe-intersect(
        $list2,
        local:safe-intersect($list3, $list4)
      )
    )
...
但是,如果任何列表为空,则该表达式将返回一个空列表。如果列表为空,是否有任何方法可以将其从交叉点中排除

解决方案: 这是我最终使用的解决方案,基于Ranon提供的答案

let $union := $list1 | $list2 | $list3 | $list4
let $results :=
    (if ($list1) then $list1 else $union)  intersect
    (if ($list2) then $list2 else $union)  intersect
    (if ($list3) then $list3 else $union)  intersect
    (if ($list4) then $list4 else $union)

我要感谢所有作出贡献的人。来自面向对象和过程的背景,而XQuery是一种函数式语言,因此我对它的理解并不自然。

如果所有列表都是空的,您可以检查它们。如果是,请将所有列表的并集指定给它们

在我的示例中,我使用了intersect和union的functx实现来实现序列的相交。也许应该编写一些函数来避免冗余代码,但为了说明这一点,这段代码很好:

import module namespace functx = "http://www.functx.com"  at ".../functx-1.0-nodoc-2007-01.xq";

let $list1 := (1,2,3)
let $list2 := (1,3)
let $list3 := ()
let $union := functx:value-union($list1, functx:value-union($list2, $list3))
let $list1a := if (count($list1) != 0) then $list1 else $union
let $list2a := if (count($list2) != 0) then $list2 else $union
let $list3a := if (count($list3) != 0) then $list3 else $union
return functx:value-intersect($list1a, functx:value-intersect($list2a, $list3a))

$union
也可以写为
($list1,$list2,$list3)
,但这将导致双元素,从而导致较大元素计数的交叉操作较慢。

如果所有列表为空,则可以检查它们。如果是,请将所有列表的并集指定给它们

在我的示例中,我使用了intersect和union的functx实现来实现序列的相交。也许应该编写一些函数来避免冗余代码,但为了说明这一点,这段代码很好:

import module namespace functx = "http://www.functx.com"  at ".../functx-1.0-nodoc-2007-01.xq";

let $list1 := (1,2,3)
let $list2 := (1,3)
let $list3 := ()
let $union := functx:value-union($list1, functx:value-union($list2, $list3))
let $list1a := if (count($list1) != 0) then $list1 else $union
let $list2a := if (count($list2) != 0) then $list2 else $union
let $list3a := if (count($list3) != 0) then $list3 else $union
return functx:value-intersect($list1a, functx:value-intersect($list2a, $list3a))

$union
也可以写为
($list1,$list2,$list3)
,但这将导致双元素,从而导致较大元素计数的相交操作较慢。

您可以将其包装在函数中并检查输入列表,而不是直接使用内置的
intersect

declare function local:safe-intersect($xs, $ys) {
  if(exists($xs) and exists($ys))
  then $xs intersect $ys
  else ($xs, $ys) (: at least one is empty :)
};
那么您的示例如下所示:

let $results := 
    $list1 intersect  
    $list2 intersect 
    $list3 intersect 
    $list4
let $results := 
    local:safe-intersect(
      $list1,
      local:safe-intersect(
        $list2,
        local:safe-intersect($list3, $list4)
      )
    )
...

您可以将其包装在函数中并检查输入列表,而不是直接使用内置的
intersect

declare function local:safe-intersect($xs, $ys) {
  if(exists($xs) and exists($ys))
  then $xs intersect $ys
  else ($xs, $ys) (: at least one is empty :)
};
那么您的示例如下所示:

let $results := 
    $list1 intersect  
    $list2 intersect 
    $list3 intersect 
    $list4
let $results := 
    local:safe-intersect(
      $list1,
      local:safe-intersect(
        $list2,
        local:safe-intersect($list3, $list4)
      )
    )
...
使用

       ( $vL1 |   ($vL2 | $vL3 | $vL4)[not($vL1)] )
  intersect
       ( $vL2 |   ($vL3 | $vL4 | $vL1)[not($vL2)] )
  intersect
       ( $vL3 |   ($vL4 | $vL1 | $vL2)[not($vL3)] )
 intersect
      ( $vL4 |   ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
  return
            ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
            ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
            ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
            ( $vL4 |   $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
    $vL2 := /*/*[. mod 3 eq 1],
    $vL3 := /*/*[. mod 4 eq 1],
    $vL4 := /*/*[. mod 5 eq 1],
    $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
   return
        ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
        ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
        ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
        ( $vL4 |   $vUniverse [not($vL4)] )
<num>01</num>
在此表达式中,
intersect
的每个参数要么是
$vN
,要么,如果
$vN
为空,则是其余集合的并集

这可以写得更简洁,如下所示:

       ( $vL1 |   ($vL2 | $vL3 | $vL4)[not($vL1)] )
  intersect
       ( $vL2 |   ($vL3 | $vL4 | $vL1)[not($vL2)] )
  intersect
       ( $vL3 |   ($vL4 | $vL1 | $vL2)[not($vL3)] )
 intersect
      ( $vL4 |   ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
  return
            ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
            ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
            ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
            ( $vL4 |   $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
    $vL2 := /*/*[. mod 3 eq 1],
    $vL3 := /*/*[. mod 4 eq 1],
    $vL4 := /*/*[. mod 5 eq 1],
    $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
   return
        ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
        ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
        ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
        ( $vL4 |   $vUniverse [not($vL4)] )
<num>01</num>
下面是一个完整的示例:

       ( $vL1 |   ($vL2 | $vL3 | $vL4)[not($vL1)] )
  intersect
       ( $vL2 |   ($vL3 | $vL4 | $vL1)[not($vL2)] )
  intersect
       ( $vL3 |   ($vL4 | $vL1 | $vL2)[not($vL3)] )
 intersect
      ( $vL4 |   ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
  return
            ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
            ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
            ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
            ( $vL4 |   $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
    $vL2 := /*/*[. mod 3 eq 1],
    $vL3 := /*/*[. mod 4 eq 1],
    $vL4 := /*/*[. mod 5 eq 1],
    $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
   return
        ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
        ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
        ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
        ( $vL4 |   $vUniverse [not($vL4)] )
<num>01</num>
在以下XML文档上计算此XQuery表达式时(使用Saxon 9.3.04 EE):

 <nums>
    <num>01</num>
    <num>02</num>
    <num>03</num>
    <num>04</num>
    <num>05</num>
    <num>06</num>
    <num>07</num>
    <num>08</num>
    <num>09</num>
    <num>10</num>
 </nums>

01
02
03
04
05
06
07
08
09
10
生成所需的正确结果

       ( $vL1 |   ($vL2 | $vL3 | $vL4)[not($vL1)] )
  intersect
       ( $vL2 |   ($vL3 | $vL4 | $vL1)[not($vL2)] )
  intersect
       ( $vL3 |   ($vL4 | $vL1 | $vL2)[not($vL3)] )
 intersect
      ( $vL4 |   ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
  return
            ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
            ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
            ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
            ( $vL4 |   $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
    $vL2 := /*/*[. mod 3 eq 1],
    $vL3 := /*/*[. mod 4 eq 1],
    $vL4 := /*/*[. mod 5 eq 1],
    $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
   return
        ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
        ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
        ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
        ( $vL4 |   $vUniverse [not($vL4)] )
<num>01</num>
01
使用

       ( $vL1 |   ($vL2 | $vL3 | $vL4)[not($vL1)] )
  intersect
       ( $vL2 |   ($vL3 | $vL4 | $vL1)[not($vL2)] )
  intersect
       ( $vL3 |   ($vL4 | $vL1 | $vL2)[not($vL3)] )
 intersect
      ( $vL4 |   ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
  return
            ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
            ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
            ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
            ( $vL4 |   $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
    $vL2 := /*/*[. mod 3 eq 1],
    $vL3 := /*/*[. mod 4 eq 1],
    $vL4 := /*/*[. mod 5 eq 1],
    $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
   return
        ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
        ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
        ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
        ( $vL4 |   $vUniverse [not($vL4)] )
<num>01</num>
在此表达式中,
intersect
的每个参数要么是
$vN
,要么,如果
$vN
为空,则是其余集合的并集

这可以写得更简洁,如下所示:

       ( $vL1 |   ($vL2 | $vL3 | $vL4)[not($vL1)] )
  intersect
       ( $vL2 |   ($vL3 | $vL4 | $vL1)[not($vL2)] )
  intersect
       ( $vL3 |   ($vL4 | $vL1 | $vL2)[not($vL3)] )
 intersect
      ( $vL4 |   ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
  return
            ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
            ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
            ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
            ( $vL4 |   $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
    $vL2 := /*/*[. mod 3 eq 1],
    $vL3 := /*/*[. mod 4 eq 1],
    $vL4 := /*/*[. mod 5 eq 1],
    $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
   return
        ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
        ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
        ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
        ( $vL4 |   $vUniverse [not($vL4)] )
<num>01</num>
下面是一个完整的示例:

       ( $vL1 |   ($vL2 | $vL3 | $vL4)[not($vL1)] )
  intersect
       ( $vL2 |   ($vL3 | $vL4 | $vL1)[not($vL2)] )
  intersect
       ( $vL3 |   ($vL4 | $vL1 | $vL2)[not($vL3)] )
 intersect
      ( $vL4 |   ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
  return
            ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
            ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
            ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
            ( $vL4 |   $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
    $vL2 := /*/*[. mod 3 eq 1],
    $vL3 := /*/*[. mod 4 eq 1],
    $vL4 := /*/*[. mod 5 eq 1],
    $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
   return
        ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
        ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
        ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
        ( $vL4 |   $vUniverse [not($vL4)] )
<num>01</num>
在以下XML文档上计算此XQuery表达式时(使用Saxon 9.3.04 EE):

 <nums>
    <num>01</num>
    <num>02</num>
    <num>03</num>
    <num>04</num>
    <num>05</num>
    <num>06</num>
    <num>07</num>
    <num>08</num>
    <num>09</num>
    <num>10</num>
 </nums>

01
02
03
04
05
06
07
08
09
10
生成所需的正确结果

       ( $vL1 |   ($vL2 | $vL3 | $vL4)[not($vL1)] )
  intersect
       ( $vL2 |   ($vL3 | $vL4 | $vL1)[not($vL2)] )
  intersect
       ( $vL3 |   ($vL4 | $vL1 | $vL2)[not($vL3)] )
 intersect
      ( $vL4 |   ($vL1 | $vL2 | $vL3)[not($vL4)] )
let $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
  return
            ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
            ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
            ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
            ( $vL4 |   $vUniverse [not($vL4)] )
let $vL1 := /*/*[. mod 2 eq 1],
    $vL2 := /*/*[. mod 3 eq 1],
    $vL3 := /*/*[. mod 4 eq 1],
    $vL4 := /*/*[. mod 5 eq 1],
    $vUniverse := $vL1 | $vL2 | $vL3 | $vL4
   return
        ( $vL1 |   $vUniverse [not($vL1)] )
      intersect
        ( $vL2 |   $vUniverse [not($vL2)] )
      intersect
        ( $vL3 |   $vUniverse [not($vL3)] )
     intersect
        ( $vL4 |   $vUniverse [not($vL4)] )
<num>01</num>
01

您确定这是正确的吗?我认为这个解决方案看起来是最优雅的,但仔细观察,结果似乎是所有列表的联合。一个测试证实了我的怀疑。@NobleK:是的,我总是通过实际运行来测试我的代码。我用一个完整的代码示例更新了我的答案,显示了这一点。出现问题的原因可能是您没有完全复制和粘贴代码,并且省略了括号。括号很重要,因为
interscect
union
具有更高的优先级。我无意侮辱你或其他什么。我以前在这里读过你们关于XQuery的一些回答,我相信你们知道自己在说什么。只是你的方法似乎真的不适合我(是的,我记得所有的括号)。我怀疑这可能与我正在使用的eXist XQuery引擎有关。我注意到它有时表现得很奇怪,产生的结果与Saxon不一样。@NobleK:NP,如果您能分享您的观察结果,eXist开发人员将不胜感激。当您运行我的代码示例时,您不会得到与我相同的结果吗?您确定这是正确的吗?我认为这个解决方案看起来是最优雅的,但仔细观察,结果似乎是所有列表的联合。一个测试证实了我的怀疑。@NobleK:是的,我总是通过实际运行来测试我的代码。我用一个完整的代码示例更新了我的答案,显示了这一点。出现问题的原因可能是您没有完全复制和粘贴代码,并且省略了括号。括号很重要,因为
interscect
union
具有更高的优先级。我无意侮辱你或其他什么。我以前在这里读过你们关于XQuery的一些回答,我相信你们知道自己在说什么。只是你的方法似乎真的不适合我(是的,我记得所有的括号)。我怀疑这可能与我正在使用的eXist XQuery引擎有关。我注意到它有时表现得很奇怪,产生的结果与Saxon不一样。@NobleK:NP,如果您能分享您的观察结果,eXist开发人员将不胜感激。当您运行我的代码示例时,您不会得到与我相同的结果吗?嗨,Ranon。我测试了这个,效果很好。我只是重新编写它来使用常规的并集和交集(因为我实际上想检查身份),我还只是测试存在性,而不是计数。我已经用我的密码更新了问题。你好,拉农。我测试了这个,效果很好。我只是用普通的工会和中间人重新编写了它