2015-06-15 25 views
2

假設有這個XML文件:選擇循環varaible的兄弟姐妹或侄女在「for」循環中的XQuery

<Adam>  
<JackSons> 
    <s1>Jack</s1> 
    <s2>Sara</s2> 
</JackSons> 
<PeterSons> 
    <s1>Peter</s1> 
    <n> 
    <s2>Anna</s2> 
    </n> 
</PeterSons> 
<DavidSons> 
    <q> 
    <s1>David</s1> 
    </q> 
    <n> 
    <s2>Suzann</s2> 
    </n> 
</DavidSons> 
</Adam> 

我想獲得s2這是每個S1的兄弟姐妹或侄女打電話內環路上兩者的功能,請注意,我們不知道除了每個s1s2有共同祖先的XML的結構什麼,我試圖

let $db := doc('test2.xq') 
for $s1 in $db//s1 
let $s2 := $db//*[//$s1]/(s2, */s2) 


return <p> {$s1/text()} marry {$s2/text()} </p> 

它返回

<p>Jack marry SaraAnnaSuzann</p> 
<p>Peter marry SaraAnnaSuzann</p> 
<p>David marry SaraAnnaSuzann</p> 

我希望

<p>Jack marry Sara</p> 
<p>Peter marry Anna</p> 
<p>David marry Suzann</p> 
+1

我沒有得到你想要達到的目標。添加預期的輸出可能會有所幫助。 –

+0

@JensErat我寫了預期的輸出 – Ahmad

+0

爲什麼那些被選中?爲了得到這個結果,你可以使用's2'。你在談論「我想選擇每個s1和s2的父母」 - 爲什麼你需要這樣做? –

回答

0

根據的複雜文本的內S1和S2,一些如下面所示,簡單的或許對你來說足夠了:

//item[starts-with(s2, s1)]/s2 

我需要查看更多真實數據以瞭解您是否需要更復雜的內容,但這應該適用於您發佈的示例。

+0

謝謝,但我的主要問題是關於獲得循環中的節點的兄弟姐妹或侄女 – Ahmad

+0

把它放在一個for循環不會改變結果。您仍將獲得相同數量的節點。 XPath和XQuery對節點序列進行操作。你可以通過在// item [開始 - (s2,s1)]/s2返回$ s2'中重寫'for $ s2來嘗試它,並且看到它給出相同的結果。 – adamretter

+0

我感到困惑,請問您可以在循環中提取s1和s2並調用它們的函數嗎? – Ahmad

2

您的查詢的問題是您再次搜索整個文檔的s2節點,而不是相同的項目。

請勿搜索s1元素,而是查找對併爲其中的每個元素打印消息。

for $pair in //item 
return <p>{ $pair//s1/text() } marry { $pair//s2/text() }</p> 

可以也期待爲s1元素,找到匹配s2節點,但這是難以閱讀和理解,並pobably執行,因爲降了回落樹找到item同屬更糟於:

for $s1 in //s1 
let $s2 := $s1//ancestor::item//s2 
return <p>{ $s1/text() } marry { $s2/text() }</p> 

在這兩種情況下,根據所允許的文檔中您可能要增加一些保障措施,只能找對二。可能最嚴格的例子是

for $pair in //item 
let $s1 := $pair//s1, $s2 := $pair//s2 
where count($s1) = 1 and count($s2) = 1 
return <p>{ $s1/text() } marry { $s2/text() }</p> 

爲了完整起見,這甚至有可能沒有明確的for循環(雖然不一定是一個合理的解決方案,因爲它會得到更難閱讀和理解,如果增長在複雜性):

//item/element p { concat(.//s1/text(), " marry ", .//s2/text()) } 
+0

非常感謝!但我需要在「for」中選擇它! – Ahmad

+0

您總是可以拆開軸的步驟並使用明確的for循環。 '// item中的$ item [s1]返回$ item // s2'。在某種程度上,軸步驟對於循環是隱含的。 –

+0

我將在循環中測試它,但是當我修改我的代碼時,我需要在循環內使用s1和s2來根據您的建議使用'let $ db:= doc('test2.xq'')來執行 – Ahmad

0

當你只知道s1s2有一個共同的祖先,你可以使用下面的代碼:

let $db := doc('test2.xq') 
for $s1 in $db//s1 
    let $item := $s1/ancestor::*[.//s1 and .//s2][not(.//*[.//s1 and .//s2])] 
    let $s2 := $item//s2 
    return <p>{ $s1/text() } marry { $s2/text() }</p> 

對於每個$s1找到既包含s1s2其中無後代包含s1s2的祖先。這是第一個共同的祖先(父母)。使用這個項目,找到相應的(兄弟姐妹或侄女)s2

+0

只是不知道爲什麼'$ db //*[.//$ s1和.//s2][not(.//*[.//$s1和.// s2])]'不會努力尋找'$ item' – Ahmad