1

まず、はい、これは宿題です - どこが間違っているのか教えてください

私は XQuery を学んでいます。私のタスクの 1 つは、パフォーマンスの曲 ID のリストを取得し、パフォーマンスの合計時間を決定することです。以下のスニペットから、songID をパフォーマンスから曲の長さに相互参照する方法を特定できる場所を教えてもらえますか?

質問の最後に私の試みをリストしました。

私の現在の XQuery コードは次のようになります。

   let $songIDs := doc("C:/Users/rob/Downloads/A4_FLOWR.xml")
                     //SongSet/Song 
   for $performance in doc("C:/Users/rob/Downloads/A4_FLOWR.xml")
                       //ContestantSet/Contestant/Performance
      return if($performance/SongRef[. =$songIDs/@SongID])   
      then <performanceDuration>{ 
             data($performance/SongRef)
           }</performanceDuration>
      else ()

どの出力:

  <performanceDuration>S005 S003 S004</performanceDuration>
  <performanceDuration>S001 S007 S002</performanceDuration>
  <performanceDuration>S008 S009 S006</performanceDuration>
  <performanceDuration>S002 S004 S007</performanceDuration>

各 S00x は曲の ID であり、参照されている xml ドキュメント (部分的なドキュメント) で見つけました。

 <SongSet>
    <Song SongID="S001">
      <Title>Bah Bah Black Sheep</Title>
      <Composer>Mother Goose</Composer>
      <Duration>2.99</Duration>
    </Song>      
    <Song SongID="S005">
      <Title>Thank You Baby</Title>
      <Composer>Shania Twain</Composer>
      <Duration>3.02</Duration>
    </Song>
    </SongSet> 

パフォーマンス セクションは次のようになります。

 <Contestant Name="Fletcher Gee" Hometown="Toronto">
    <Repertoire>
      <SongRef>S001</SongRef>
      <SongRef>S002</SongRef>
      <SongRef>S007</SongRef>
      <SongRef>S010</SongRef>
    </Repertoire>
    <Performance>
      <SongRef>S001</SongRef>
      <SongRef>S007</SongRef>
      <SongRef>S002</SongRef>
    </Performance>
    </Contestant>

私の試み

ネストされたループを使用すると思っていましたが、失敗しました:

 let $songs := doc("C:/Users/rob/Downloads/A4_FLOWR.xml")
               //SongSet/Song 
   for $performance in doc("C:/Users/rob/Downloads/A4_FLOWR.xml")
                       //ContestantSet/Contestant/Performance
   return if($performance/SongRef[. =$songs/@SongID])   
     for $song in $songIDs 
          (: gives an error in BaseX about incomplete if :)
   then <performanceDuration>{ 
          data($performance/SongRef)
        }</performanceDuration>
   else ()

- 編集 -

内側のループを修正しましたが、ID に一致する曲だけでなく、すべての曲の長さを取得しています。これは可変スコープによるものだと感じていますが、よくわかりません:

 let $songs := doc("C:/Users/rob/Downloads/A4_FLOWR.xml")//SongSet/Song 
   for $performance in doc("C:/Users/rob/Downloads/A4_FLOWR.xml")//ContestantSet/Contestant/Performance
   return if($performance/SongRef[. =$songs/@SongID])   

   then <performanceDuration>{  
     for $song in $songs
     return if($performance/SongRef[. =$songs/@SongID]) 
     then      
      sum($song/Duration)
     else ()
  }</performanceDuration>
   else ()

}

出力:

<performanceDuration>2.99 1.15 3.15 2.2 3.02 2.25 3.45 1.29 2.33 3.1</performanceDuration>
4

1 に答える 1

1

当面の問題は構文です。条件と条件内のキーワード「then」の間に内部ループを挿入しました。最初にそれを修正してください:

return if ($performance/SongRef = $songs/@SongID) then
          <performanceDuration>{
             (: put your inner loop HERE :)
          }</performanceDuration>
else ()

performanceDuration 要素内のクエリ エバリュエーターの状況を考えてみましょう。変数 $performance があり、$performance/SongRef を使用してすべての曲の参照を見つけることができます。また、パフォーマンス要素の各曲の参照について、SongRef 値を $songs/@SongID と照合することで、対応する曲の要素を見つけることができます。

この時点での次のステップは、次のように自問することです。

  • 特定の曲の参照について、その曲の曲要素と、その曲の長さを見つけるにはどうすればよいですか?
  • 一連の期間の合計を取得する方法はありますか? たとえば、sum()機能はありますか?(確かにあると思いますが、この時点では常に関数と演算子の仕様を調べて、署名を確認しています。)
  • 期間情報にはどのような種類がありますか? 私はそれが分と秒であると予想し、期間の計算について心配していますが、あなたのサンプルは小数のように見えるので簡単です。
于 2013-07-28T00:10:42.587 に答える