如何在xquery的上下文中为for循环工作,包含'?

时间:2015-03-31 16:23:01

标签: xpath xquery

如果我们有像

这样的books.xml文件
<books>
    <book isbn="123">
        <collections>
            <collection c="1" />
            <collection c="2" />
            <collection c="3" />
            <collection c="4" />
        </collections>
    </book>
    <book isbn="234">
        <collections>
            <collection c="1" />
            <collection c="2" />
            <collection c="3" />
            <collection c="5" />
        </collections>
    </book>
</books>

我想要返回两本书属于相同馆藏的所有ISBN。

declare variable $doc := doc("books.xml");
<samecollections>
{ 
    for $b1 in $doc/books/book
    for $b2 in $doc/books/book
    where $b1 << $b2 and
        every $p in $b1/collections/collection 
        satisfies $p in $b2/collections/collection
    return 
    ...
}
</samecollections>

我如何制作类似的作品?我尝试在where循环中插入for循环,但没有任何效果,所以我认为我真的误解了xquery的语法。帮助

1 个答案:

答案 0 :(得分:0)

理想情况下,您的XQuery处理器支持group by,因此答案非常简单:

for $b in $books/book
let $colls-key := string-join($b/collections/collection/@c, '')
group by $colls-key
return element grouped {
    $b/@isbn/string()
}

如果收藏品始终没有在数据中订购,您可以在生成密钥之前订购它们:

let $colls-key := 
  string-join(
    for $c in $collections/collection/@c
    order by $c
    return $c)

如果没有group by,它就会变得更加混乱。

declare function local:key($collections){
  string-join($collections/collection/@c, '')
};

for $key in distinct-values($doc/books/book/local:key(collections))
return element grouped {
  $doc/books/book[local:key(collections) eq $key]/@isbn/string()
}

取决于XQuery处理器也可能效率较低,因此对于大型数据集可能不建议。如果性能是一个问题,那么您可以查看可用于特定实现的优化。