XQuery for循环产生重复的结果

时间:2013-09-11 21:14:29

标签: xml xquery exist-db

我正在使用XQuery来分析具有相同XML结构的两组测试结果。下面的函数创建了一组新元素,这些元素是两个结果集的测试用例的单独比较。对于每个测试用例,两组之间应该存在1-1关系,但我的代码有时会产生8次比较,我无法弄清楚原因!

这是我的输入XML,用于具有不同数据的两个集合(例如缩写):

 <tests>
  <test-group name="TestA">
    <test-case name="CaseA1" success="true"/>
    <test-case name="CaseA2" success="false"/>
    <test-case name="CaseA3" success="true"/>
  </test-group>
  <test-group name="TestB">
    <test-case name="CaseB1" success="false"/>
    <test-case name="CaseB2" success="false"/>
    <test-case name="CaseB3" success="true"/>
  </test-group>
  <test-group name="TestC">
    <test-case name="CaseC1" success="false"/>
    <test-case name="CaseC2" success="false"/>
    <test-case name="CaseC3" success="true"/>
  </test-group>
</tests>

示例输出:

 <test-state delta1="15" delta2="false" isPass="true" fixture="TestA" case="CaseA1"/>
 <test-state delta1="12" delta2="true" isPass="false" fixture="TestA" case="CaseA1"/>
 <test-state delta1="5" delta2="false" isPass="true" fixture="TestA" case="CaseA1"/>
 <test-state delta1="15" delta2="false" isPass="true" fixture="TestC" case="CaseC1"/>
 <test-state delta1="12" delta2="true" isPass="false" fixture="TestC" case="CaseC1"/>
 <test-state delta1="5" delta2="false" isPass="true" fixture="TestC" case="CaseC1"/>

这是我的Xquery(例如修改):

declare function app:runReport() {
    let $new-run := collection('collection1')
    let $old-run := collection('collection2')    
    return 
<report> 
    {         
    for $new-case in $new-run//test-case,
        $old-case in $old-run//test-case
        where $new-case/@name = $old-case/@name and $new-case/../@name = $old-case/../@name
            return
                let $new-msg := xs:string($new-case/message)
                let $old-msg := xs:string($old-case/message)
                let $new-len := string-length($new-msg)
                let $old-len := string-length($old-msg)
                let $msg-dif := $new-len - $old-len

                let $delta1 := fn:compare(xs:string($new-case/@success),xs:string($old-case/@success)) = 0
                let $delta2 := abs($msg-dif)
                return        
                   <test-state 
                          delta1="{$delta1}"
                          delta2="{$delta2}"
                          isPass="{$new-case/@success}"
                         fixture="{$new-case/../@name}"
                            case="{$new-case/@name}"
                            path="unknownPath"/>
    }        
</report>
};

在我看来,它对$ case-case和$ case之间的每个组合进行了排列,但我不明白为什么。我会尝试过滤掉重复的内容,但它们不是完全相同的,它似乎有时使用$ old-case代替$ new-case。

2 个答案:

答案 0 :(得分:1)

  

在我看来,它对$ new-case和$ old-case之间的每个组合进行了排列

凭借for的结构,这正是正在发生的事情。例如:

for $x in (1, 2, 3), $y in ('a', 'b', 'c')
return <z>{$x, $y}</z>

=&GT;

<z>1 a</z>
<z>1 b</z>
<z>1 c</z>
<z>2 a</z>
<z>2 b</z>
<z>2 c</z>
<z>3 a</z>
<z>3 b</z>
<z>3 c</z>

相反,您可以查找匹配的旧测试:

for $new-case in $new-run//test-case
let $old-case := $old-run//test-case[@name = $new-case/@name]
return
...

答案 1 :(得分:1)

猜测一下,您的两个输入与您向我们展示的样本有所不同,影响关键比较$new-case/@name = $old-case/@name and $new-case/../@name = $old-case/../@name - 在新集合或旧集合或两者中,......的组合@name和./@name不是唯一的。

要查找数据中的重复项,我会运行如下查询:

let $new-run := collection('collection1'),
    $old-run := collection('collection2')    
for $name in distinct-values(
        for $tc in ($new-run | $old-run)//test-case/@name
        return concat($tc/../@name,' || ',$tc/@name) 
    )
let $old := $old-run//test-case
            [concat(../@name,' || ', @name) = $name],
    $new := $new-run//test-case
            [concat(../@name,' || ', @name) = $name]
where count($old) gt 1 
   or count($new) gt 1
return <duplicate-id name="{$name}"
                     old-count="{count($old)}"
                     new-count="{count($new)}"/>