使用XQuery删除xml节点

问题描述 投票:1回答:2

我有下面的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
};

当我试着执行这段代码时,我得到一个错误,说他停止了,期待第二个函数的 "返回"。有谁知道我在这种情况下做错了什么?

xml xquery basex
2个回答
2
投票

你的整个方法在本质上感觉不是很实用。使用BaseX删除元素最好使用 XQuery更新.

所以在你的情况下,你只需使用下面的函数删除所有图书元素。

declare function local:process-xml($element) {
  $element update delete node .//book[not(./*[(genre='Java')and(genre='Webservice')])] 
};

0
投票

你可以使用一个递归函数来过滤掉所有的图书元素 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
};
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.