选择"中可选择的循环的兄弟或侄女,用于"循环在XQuery中

时间:2015-06-15 09:42:32

标签: xml loops xquery

假设有这个XML文件:

<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的兄弟或侄女在循环内调用它们的两个函数,请注意我们对XML的结构一无所知。每个s1s2都有一个共同的祖先,我试过

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>

3 个答案:

答案 0 :(得分:2)

您的查询的问题是您再次在整个文档中搜索s2个节点,而不是同一个项目。

不要搜索s1元素,但要查找对并为每个元素打印一条消息。

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

可能也会查找s1个元素并找到匹配的s2个节点,但是这很难阅读和理解,并且可能因为下降回来而表现更差在树下找到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()) }

答案 1 :(得分:0)

根据s1和s2中文本的复杂程度,以下内容对您来说可能就足够了:

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

我需要查看更多真实数据,以了解您是否需要更复杂的内容,但这应该适用于您发布的示例。

答案 2 :(得分: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