xquery返回两个带有两个谓词的元素?

时间:2011-12-01 18:58:09

标签: xml xpath 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>        `

3 个答案:

答案 0 :(得分:3)

您正在返回布尔值(true或false),因为您正在使用布尔表达式(X and Y)。如果要返回两个节点序列的并集,请改为使用管道符号(X | Y),或者如果需要X之前的序列,请使用逗号(X,Y)。或者,如果要返回两个字符串的串联,请使用concat()函数(如下面的示例所示)。

我想也许你并不理解&#34;对于&#34;表达工作。 $ x变量绑定到&#34; in&#34;之后的表达式返回的任何节点序列。因此,在您的情况下,$ x绑定到一个<Book>元素(或者,根据您的XQuery实现,可能是数据库中的所有<Book>个文档元素)。由于$ x绑定到<Book>,这意味着您的查询基本上是这样说的(如果您首先进行上述更正,则替换&#34;以及&#34;使用&#34; |&#34;): &#34;如果此<Book>文档中包含任何<Occupation>元素&#34; Builder&#34;以及带有&#34; M&#34;的所有<Sex>个元素,然后返回所有<Book>个文档的<Name><LastName>文本节点子节点。

所以看起来你真正想要的是将$ x绑定到<Person>元素(假设<Person>显示为<Book>的子元素,而您的示例XML并没有这样做。 t指定):

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

注意我做了一些改动。我删除了&#34; //&#34;赞成&#34; /&#34;,因为您的示例XML显示<Occupation><Sex><Name><LastName>是{{1}的子项}。只使用&#34; //&#34;如果你不知道元素可能出现在哪里(n级深),原因有两个:

  1. &#34; //&#34;比#34; /&#34;慢,因为这意味着XQuery引擎必须搜索更多的地方,并且
  2. 你的代码暗示了错误的东西:这些元素可以显示为后代(并且不一定总是显示为直接子代)。
  3. 我还添加了concat()函数,因为我怀疑它接近你试图提取的内容。

    我还摆脱了<Person>节点测试。一般来说,你不需要它们(并且应该避免它们)。你真正想要做的是比较每个元素的字符串值,而不是每个文本节点子元素的字符串值。您可能知道每个元素只有一个文本节点子节点,但是没有理由编写在这种情况下会破坏的代码:

    text()

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

    我也替换了#34; =&#34;与&#34; eq&#34;,因为&#34; =&#34;用于比较可能的多个序列和&#34; eq&#34;仅用于比较奇异序列。

    最后,你甚至不需要这个用例的FLWOR表达式。您也可以将其写为路径表达式:

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

答案 1 :(得分:2)

“和”是一个布尔运算符 - 结果始终为true或false。在英语中我们可能会使用“和”来获得两组的联合(“给我书中的作者和标题”),在逻辑'和'中总是结合两个布尔(如果作者和作者同时author and title是真的。标题存在)。所以你的“and”运算符需要被一个“union”运算符替换,或者其他结合了结果的东西,比如concat()或“,”。

另一个问题是运营商优先级。通常,如果return子句包含任何非平凡的表达式,那么将parens放在它周围是最安全的。你想要

for $x in X return (a, b)

(for $x in X return a), b

答案 2 :(得分:0)

“return”子句之后指定的表达式在逻辑操作中组合,该操作始终返回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())