XQuery:选择不同的节点

时间:2014-04-17 17:32:35

标签: xml xquery distinct-values

我正在尝试学习XQuery,但我还没想出如何在我创建的以下xml文件中选择不同的教师。我查找了distinct-values()但它似乎只返回一个字符串序列。如果我想只运行XQuery而不声明功能,如functx:distinct-deep和functx:来自http://www.xqueryfunctions.com/xq/c0015.html#c0053的不同节点,我是否有办法选择在信用和非学分课程中教授的不同教师在同一年下面的xml文件?我很感激你的帮助。谢谢。

<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>

如果我使用distinct-values,则返回一系列字符串:      HansonJohn LeeSandra

2 个答案:

答案 0 :(得分:1)

一种可能的解决方案是:

  1. 查找同年内在学分和非学分模块中授课的所有教师。

  2. 过滤这些教师,使他们与众不同。我使用尾递归函数local:distinct-teachers来实现这一点,它在(1)中找到的所有教师的序列上运行。它依次检查每位教师,如果之前没有看到,则将其添加到$distinct教师的累加器中。

    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, ())
    

答案 1 :(得分:0)

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

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