如何在使用XQuery获取其ID时查找歌曲的持续时间?

时间:2013-07-27 23:38:31

标签: xquery

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

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

我在问题的最后列出了我的尝试。

我当前的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>

1 个答案:

答案 0 :(得分: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匹配来找到相应的歌曲元素。 / p>

此时我的下一步是问问自己:

  • 对于给定的歌曲参考,如何找到该歌曲的歌曲元素,然后是该歌曲的持续时间?
  • 有没有办法获得一些持续时间的总和?例如,有sum()函数吗? (我很确定有,但在这一点上,我总是提取函数和操作符规范,并查看它以确保签名。)
  • 持续时间信息的类型是什么?我希望它是几分钟和几秒钟,我会担心持续时间算术,但是你的样本看起来像小数,这很容易。