2014-04-17 52 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,())