如何比较xml文件中的两个元素?

时间:2015-03-31 16:48:35

标签: xml xquery

所以我有以下xml文件:

<!DOCTYPE music SYSTEM "music.dtd">
<music>
 <songs>
   <song sid = "s1" time = "2:04" year = "1994">
     <title>Thriller </title>
     <artist>Michael </artist>
       <composers>
          <composer>Michael</composer> 
       </composers>
     <album> Thriller album</album>
    </song>
   <song sid = "s2" time = "2:00" year = "1999">
     <title> Billy </title>
     <artist> Thomas </artist>
     <composers>
       <composer> Rick </composer> 
     </composers>
     <album> The one </album>
    </song>
    <song sid = "s3" time = "1:50" year = "2000">
      <title> Down </title>
      <artist> PJ </artist>
      <composers>
        <composer>Jerry </composer>
      </composers>
      <album>Forty </album>
    </song>
 </songs>
 <playlists>
   <playlist pid = "p1" creator = "Tom">
     <track sid = "s1"/>
   </playlist>
 </playlists>


</music>

我想要做的是从不在播放列表中的歌曲中获取所有sid 所以在这个xml文件中,我希望有一个查询返回sid:s2和s3,因为这两个都不在播放列表中,因为s1在播放列表中,所以不应该返回。

我试图使用此查询:

for $x in doc("music.xml")/music/songs/song/@sid
  return <sid>{data($x)}</sid>

我试图将其结果存储在一个变量中,以便稍后我可以将它与另一个遍历播放列表的查询进行比较,但我对如何将查询结果存储到变量中有点迷失。有帮助吗?感谢。

2 个答案:

答案 0 :(得分:2)

您可以使用let子句绑定查询中的变量。这是一个包含几个中间变量的例子:

let $doc := doc("music.xml")/music
let $in-pl := $doc/playlists/playlist/track
let $not-in-pl := $doc/songs/song[fn:not(@sid = $in-pl/@sid)]
for $x in $not-in-pl/@sid
return <sid>{data($x)}</sid>

这里的关键表达是$doc/songs/song[fn:not(@sid = $in-pl/@sid)]。这使用一般相等比较操作=,它可以比较序列(0或更多项)。 fn:not()函数会取消比较结果,因此此表达式会选择song@sid元素,其中@sid不等于任何播放列表轨道的return <noplaylist> { for $x in $not-in-pl/@sid return <sid sid="{ data($x) }"/> } </noplaylist> 属性。

如果要在多个查询中存储中间结果,则需要使用不同的方法,具体取决于您的XQuery处理器/环境。某些XML数据库允许您存储跨查询持久存储的服务器/会话字段。对于其他人,您需要将中间结果存储在文档中。您使用的XQuery处理器是什么?

<强>更新

在XQuery中构造元素有多种方法。您可以使用元素文字,在其中转义XQuery表达式:

return
  element noplaylist {
    for $x in $not-in-pl/@sid
    return
      element sid {
        attribute sid { data($x) }
      }
  }

或者您可以使用XQuery元素/属性构造函数:

{{1}}

答案 1 :(得分:0)

是的,我试过这个:

 for $x in doc("music.xml")/music/songs/song/@sid
  where $x != doc("music.xml")//playlists/playlist/track/@sid
  return <sid>{data($x)}</sid>

我不确定它是否巧合,但现在才有意义..