2015-03-31 3 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 вы используете?

Update:

Есть несколько способов построить элементы в 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

+0

выглядит как ваш вопрос получил отрезанный – joemfb

+0

Как бы я его возвращал как user125535

Смежные вопросы