2011-12-01 178 views
0

我試圖從這個名單中得到一個名單 - 但它只是讓我回「真」 - 我做錯了什麼?xquery返回兩個謂詞的元素?

for $x in /Book 
where $x//Occupation/text()="Builder" and $x//Sex/text()="M" 
return $x//Name/text() and $x//LastName/text() 

我在哪裏出錯了?

示例XML的: '.....

<Person> 

    <Name>Mathew</Name> 

    <LastName>Michaels</LastName> 

    <Relation>Father</Relation> 

    <Religion>Roman Catholic</Religion> 

    <Education>Read</Education> 

    <Age>83</Age> 

    <Sex>M</Sex> 

    <Occupation>Builder</Occupation> 

    <Maried>Widower</Maried> 

    <PlaceOfBirth>Co. Kildare</PlaceOfBirth> 

</Person>  ` 
+0

我已經計算出東西是給我更喜歡我需要的答案的格式,但仍然沒有正確的答案 - '讓$一個:= /文檔//職業/ text()='Builder' let $ b:=/Document // Sex/text()='M' return(// Name)|(// LastName)' – nevermind

+0

如果你想返回對''和''元素,這裏是我的答案結尾處的路徑表達式的修改版本:'/ Book/Person [職業等式Builder]] [S ex eq「M」] /(Name,LastName)' –

+0

請注意,上面的註釋中的示例將$ a和$ b綁定到布爾值,這可能不是您想要的。這就像是說:「如果有任何''元素具有'生成器文本節點子元素',讓$ a爲真。 –

回答

3

你,因爲你使用的是布爾表達式(X and Y)返回一個布爾值(true或false)。如果要返回兩個節點序列的並集,請改用管道符號(X | Y),或者如果您想要X在Y之前的序列,請使用逗號(X,Y)。或者如果你想返回兩個字符串的連接,使用concat()函數(如下面的例子)。

我想也許你不瞭解「for」表達式是如何工作的。 $ x變量綁定到「in」之後的表達式返回的任何節點序列。所以在你的情況下,$ x綁定到一個<Book>元素(或者,根據你的XQuery實現,可能是數據庫中的所有<Book>文檔元素)。由於$ x綁定到<Book>,這意味着您的查詢基本上是這樣說的(如果您首先進行上述更正,則將「and」替換爲「|」):「如果此<Book>文檔具有帶」Builder「的任何<Occupation>元素<Sex>元素與「M」,然後返回所有<Book>文檔的<Name><LastName>文本節點孩子。

所以它看起來像你真正想要的是給$ x綁定到<Person>元素,而不是(假設<Person>出現的孩子<Book>,您的示例XML未指定):

for $x in /Book/Person 
where $x/Occupation eq "Builder" and $x/Sex eq "M" 
return concat($x/Name,' ',$x/LastName) 

注意我做了一些更改。我刪除了「//」以支持「/」,因爲您的示例XML顯示<Occupation><Sex><Name><LastName><Person>的子項。只能用「//」,如果你不知道在哪裏的元素可能會出現(正層次深),原因有二:

  1. 「//」比「/」慢,因爲這意味着中的XQuery引擎必須搜索更多的地方,並且
  2. 你的代碼暗示了錯誤的東西:這些元素可能以後代的形式出現(並且不一定總是作爲直接的孩子出現)。

我還添加了concat()函數,因爲我懷疑它接近你想要提取的東西。

我也擺脫了text()節點測試。一般來說,你不需要它們(並且應該避免它們)。你真正想要做的是比較每個元素的字符串值,而不是每個文本節點子元素的字符串值。你可能知道,每一個元素只會有一個文本節點孩子,但沒有理由編寫的代碼,將在情況下打破這樣的:

<Religion>Roman <!--comment-->Catholic</Religion> 

<PlaceOfBirth><b>Co.</b> Kildare</PlaceOfBirth> 

我也改爲「=」與「eq」相關,因爲「=」用於比較可能的多個序列,而「eq」僅用於比較單數序列。

最後,您甚至不需要此用例的FLWOR表達式。你也可以把它寫成一個路徑表達式:

/Book/Person[Occupation eq "Builder"][Sex eq "M"]/concat(Name,' ',LastName) 
+0

謝謝 - 當解釋時,這是可以理解的。我誤解了for子句的含義,因此無法得到我期待的結果。 Person元素在Book文檔中有幾個層次,所以我在//中添加了,因爲會有太多的步驟來實現它。在w3學校的xquery上進行在線課程後,有很多東西被遺漏。 (你今天有兩次對我有幫助:))非常感謝。 – nevermind

+0

不客氣!哦,你可能會發現這個網站的利益。 ;-) http://w3fools.com/ –

+0

哈!我看了一下。有趣的東西好吧。再次感謝 – nevermind

0

「返回」子句後指定的表達式組合在邏輯運算,它總是返回truefalse。下面的兩個版本可能會做你想要什麼:

for $x in /Book 
where $x//Person/text()="Builder" and $x//Place/text()="F" 
return ($x//Name/text(), $x//LastName/text()) 

for $x in /Book 
where $x//Person/text()="Builder" and $x//Place/text()="F" 
return ($x//Name/text() | $x//LastName/text()) 
+0

我在[]中加入了謂詞,但它只是返回一長串文本名字,而不是所有的人都來自地方F.感謝嘗試。 – nevermind

+0

如果您顯示一些示例XML數據,它可以幫助我們找出錯誤的位置。 –

+0

@EvanLenz希望這是有道理的 - 它只是整個事物的一部分。 – nevermind

2

「和」是一個布爾運算符 - 結果總是爲真或假。而在英語中,我們可能會用「和」來獲得兩組的聯合(「給我這本書的作者和標題」),邏輯上'和'總是結合兩個布爾(所以author and title如果作者和標題都存在,則爲true)。因此,您的「和」運算符需要由「聯合」運算符或結合結果的其他內容(如concat()或「,」)替換。

另一個問題是運算符的優先級。一般來說,如果返回子句包含任何不重要的表達式,那麼最好放置它。你想

for $x in X return (a, b) 

(for $x in X return a), b