2015-03-31 90 views
1

所以我有以下XML文件:如何比较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

您可以使用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属性。

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

更新

有多种方式来构建它的元素。您可以使用元素的文字,里面逃脱他们的XQuery表达式:

return 
    <noplaylist> 
    { 
    for $x in $not-in-pl/@sid 
    return 
     <sid sid="{ data($x) }"/> 
    } 
    </noplaylist> 

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

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

um..so我想这:

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

我不知道这是否巧合,但现在有道理..

+0

这也可以!如果要在变量中捕获该表达式的结果,请在它之前添加'let $ results:=',并在其后面添加'return $ results'(或其他表达式)。 XQuery非常灵活;) – joemfb 2015-03-31 17:02:51

+0

看起来像你的问题得到了切断 – joemfb 2015-03-31 17:04:35

+0

我将如何返回它作为 user125535 2015-03-31 17:07:05