2014-04-17 114 views
1

我想学习XQuery,我还没有想出如何在我所做的以下xml文件中选择不同的教师。我查了distinct-values(),但它似乎只返回一串字符串。如果我只想运行XQuery而不声明函数如functx:distinct-deep和functx:来自http://www.xqueryfunctions.com/xq/c0015.html#c0053的distinct-nodes,是否有一种方法可以选择同一年在信用和非信用课程中教过的不同教师从下面的XML文件?我会很感激你的帮助。谢谢。XQuery:选择不同的节点

<DB> 
<credit> 
<course_title>biology101</course_title> 
    <teacher> 
     <lastname>Smith</lastname> 
     <firstname>Amy</firstname> 
    </teacher> 
    <teacher> 
     <lastname>Hanson</lastname> 
     <firstname>John</firstname> 
    </teacher> 
    <teacher> 
     <lastname>Lee</lastname> 
     <firstname>Sandra</firstname> 
    </teacher> 
    <year>2013</year> 
</credit> 
<credit> 
<course_title>chemistry101</course_title> 
    <teacher> 
     <lastname>Richardson</lastname> 
     <firstname>Rob</firstname> 
    </teacher> 
    <teacher> 
     <lastname>Hanson</lastname> 
     <firstname>John</firstname> 
    </teacher> 
    <year>2013</year> 
</credit> 
<noncredit> 
<course_title>physics101</course_title> 
    <teacher> 
     <lastname>Hanson</lastname> 
     <firstname>John</firstname> 
    </teacher> 
    <teacher> 
     <lastname>Head</lastname> 
     <firstname>Peter</firstname> 
    </teacher> 
    <year>2013</year> 
</noncredit> 
<noncredit> 
<course_title>physics101</course_title> 
    <teacher> 
     <lastname>Lee</lastname> 
     <firstname>Sandra</firstname> 
    </teacher> 
    <teacher> 
     <lastname>Head</lastname> 
     <firstname>Peter</firstname> 
    </teacher> 
    <teacher> 
     <lastname>Hanson</lastname> 
     <firstname>John</firstname> 
    </teacher> 
    <year>2013</year> 
</noncredit> 
</DB> 

我用下面的XQuery:

let $DB := doc("myDB.xml") /DB 
let $credit_teacher := $DB/credit/teacher 

for $noncredit_teacher in $DB/noncredit/teacher 
where $DB/credit/year = $DB/noncredit/year 
and $credit_teacher/lastname = $noncredit_teacher/lastname 
and $credit_teacher/firstname = $noncredit_teacher/firstname 
return $noncredit_teacher 

但复制教师返回:

<teacher> 
    <lastname>Hanson</lastname> 
    <firstname>John</firstname> 
</teacher> 
<teacher> 
    <lastname>Lee</lastname> 
    <firstname>Sandra</firstname> 
</teacher> 
<teacher> 
    <lastname>Hanson</lastname> 
    <firstname>John</firstname> 
</teacher> 

如果我使用不同的值,则返回字符串的序列: HansonJohn LeeSandra

回答

0

您已经选择了不同的节点。您正在选择的教师节点在源XML中重复,因此具有单独的节点标识。

您必须根据节点内容进行某种形式的重复数据删除。 functx:distinct-nodes()functx:distinct-deep就是这种重复数据删除的好例子。

+0

joemfb,感谢您的咨询。我尝试使用functx:distinct-nodes()和functx:distinct-deep,但仍然得到相同的结果,没有任何重复数据删除。你知道我可以尝试的其他方法吗?再一次感谢你。 – jf1034

1

一个可能的解决方案是:

  1. 找到所有已教信贷和非信贷模块在同一年度内的教师。

  2. 过滤这些教师,使他们不同。我已经使用了一个尾递归函数local:distinct-teachers来实现这个功能,它对(1)中找到的所有教师的顺序进行操作。它依次检查每位教师,如果以前没有看到,则将其添加到教师的累加器中。

    declare function local:distinct-teachers($teachers as element(teacher)*, $distinct as element(teacher)*) as element(teacher)* { 
        if(empty($teachers)) then 
        $distinct 
        else 
        let $teacher := $teachers[1] 
        return 
         let $new-distinct := if($distinct/.[lastname eq $teacher/lastname] 
          [firstname eq $teacher/firstname] 
        ) then 
          $distinct 
         else 
          ($teacher, $distinct) 
         return 
          local:distinct-teachers($teachers[position() gt 1], $new-distinct) 
    }; 
    
    
    let $teachers := 
        let $credit-teachers := doc("myDB.xml")/DB/credit/teacher 
        let $non-credit-teachers := doc("myDB.xml")/DB/noncredit/teacher 
        return 
         for $credit-teacher in $credit-teachers 
         for $non-credit-teacher in $non-credit-teachers 
         return 
          $credit-teacher 
           [lastname eq $non-credit-teacher/lastname] 
           [firstname eq $non-credit-teacher/firstname] 
           [following-sibling::year eq $non-credit-teacher/following-sibling::year] 
    return 
        local:distinct-teachers($teachers,())