1

首先,是的,这是作业-请指出我哪里出错了,但请不要为我做作业

我正在学习 XQuery,我的任务之一是获取表演的歌曲 ID 列表并确定表演的总持续时间。鉴于下面的片段,任何人都可以指出我在哪里可以确定如何交叉引用从表演到歌曲持续时间的歌曲 ID?

我在问题的末尾列出了我的尝试。

我当前的 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 找到所有歌曲引用,并且对于 performance 元素中的每个歌曲引用,您可以通过将 SongRef 值与 $songs/@SongID 匹配来找到相应的歌曲元素。

在这一点上,我的下一步是问自己:

  • 对于给定的歌曲参考,我如何找到该歌曲的歌曲元素,以及该歌曲的持续时间?
  • 有没有办法得到一些持续时间的总和?例如,是否有一个sum()函数?(我很确定有,但在这一点上,我总是拉起函数和运算符规范并查找它以确保签名。)
  • 持续时间信息有什么类型?我希望它是分钟和秒,我会担心持续时间的算术,但你的样本使它看起来像小数,这很容易。
于 2013-07-28T00:10:42.587 回答