我有下面的xml,我需要用XQuery对xml进行过滤,所以最后,我有以下结果:
<?xml version="1.0" encoding="UTF-8"?>
<publication>
<scientificPublication>
<id>2347823476</id>
<book>
<chapter>
<author>Tom</author>
<genre>Java</genre>
<genre>Webservice</genre>
</chapter>
</book>
<book>
<chapter>
<author>Mike</author>
<genre>C</genre>
<genre>Machine Learning</genre>
</chapter>
</book>
<book>
<chapter>
<author>William</author>
<genre>JavaScript</genre>
<genre>Frontend</genre>
</chapter>
</book>
</scientificPublication>
</publication>
我需要用XQuery对xml进行过滤,所以最后,我有以下结果。
<?xml version="1.0" encoding="UTF-8"?>
<publication>
<scientificPublication>
<id>2347823476</id>
<book>
<chapter>
<author>Tom</author>
<genre>Java</genre>
<genre>Webservice</genre>
</chapter>
</book>
</scientificPublication>
</publication>
基本上我的想法是找到第一本书中的所有兄弟节点 然后用函数删除它们。fn:remove((item,item,...),position)
. 所以我用下面的xpath找到了所有需要删除的节点。
publication/*/book[not(./*[(genre='Java')and(genre='Webservice')])]
然后我试着用这段代码把它们从xml中删除。
declare function local:process-xml($element) {
let $orig := $element
let $toFilter := $element/*/book[not(./*[(genre='Java')and(genre='Webservice')])]
let $el := local:filter($orig, $toFilter)
return $el
};
declare function local:filter($elements, $toFilter) {
for $i in $toFilter
let $pos := position()
remove($lements, $pos)
return $elements
};
当我试着执行这段代码时,我得到一个错误,说他停止了,期待第二个函数的 "返回"。有谁知道我在这种情况下做错了什么?
你的整个方法在本质上感觉不是很实用。使用BaseX删除元素最好使用 XQuery更新.
所以在你的情况下,你只需使用下面的函数删除所有图书元素。
declare function local:process-xml($element) {
$element update delete node .//book[not(./*[(genre='Java')and(genre='Webservice')])]
};
你可以使用一个递归函数来过滤掉所有的图书元素 book
元素。
declare function local:filter($node)
{
typeswitch($node)
case element(book) return
if ($node[not(*[(genre='Java') and (genre='Webservice')])])
then () (: we don't want these books, so return empty sequence :)
else $node (: this is the book we want :)
case element() return
element { fn:node-name($node) } {
$node/@*,
$node/node() ! local:filter(.)
}
default return $node
};