在使用eXist-db和XQuery存储数据之前更新内存节点

时间:2017-03-15 15:04:28

标签: xml xquery exist-db

我正在使用eXist-db创建基于Web的数据库应用程序。 我希望将用户在使用XForms创建的公式中插入的数据保存到数据库中。为此,整个数据结构保存在变量$content中,我使用XQuery模块存储在数据库中:

declare
    %rest:PUT("{$content}")
    %rest:path("/items")
function ffdb:change-items($content as node()*) {
    let $data := <items>
            { $content/items/* }
        </items>

    let $stored := xmldb:store($config:app-root, "1234.xml", $data)

    return
        doesnotmatter:function()
};

在此示例中,$ content包含以下节点集:

<items>
    <item1>A</item>
    <item2>B</item>
    <itemlist>
        <item3>C</item3>
    <itemlist/>
<items>

工作正常。我现在的问题是,在将其存储到数据库中之前,我想在$ content / items / itemlist中插入内容为“D”的节点。存储结果应为:

<items>
    <item1>A</item>
    <item2>B</item>
    <itemlist>
        <item3>C</item3>
        <item3>D</item3>
    <itemlist/>
<items>

这似乎比我想象的更困难。我想我试图改变查询一百次。 当我尝试直接在$content中插入节点集时,我得到的消息是XQuery更新表达式无法应用于内存节点。 当我在声明数据存储后尝试在$data中插入节点集时,但遗憾的是没有节点集。

我还从https://github.com/ryanjdew/XQuery-XML-Memory-Operations安装了模块,然后在开头插入:

let $content2 := mem:copy($content) !
    ( 
    mem:insert-child(., $content/items/itemlist, attribute new-attribute {"item3"}),
    mem:execute(.))

之后我在声明$ data时插入$ content2而不是$content。我收到的消息如下:

org.exist.xquery.XPathException: mem-op:MIXEDSOURCES The nodes to change are coming from multiple sources [at line 249, column 3, source: /db/apps/myapp/modules/memoryoperations/memory-operations-pure-xquery.xqy]

不知道该怎么做。我还尝试在存储文档后加载文档并在此处插入节点集,这样我就不会更改内存中的数据,但这也不起作用。未插入节点集。

1 个答案:

答案 0 :(得分:0)

您已经确定eXist的XQuery Update工具不支持内存中的操作。除了身份转换(例如,使用XSLT或a recursive application of XQuery's typeswitch expression之外,您发现的&#34;纯xquery&#34;版本的Ryan J. Dew的库是可行的选择。

假设您已下载https://github.com/ryanjdew/XQuery-XML-Memory-Operations存储库,解压缩并将生成的文件夹上传到/db/apps,此代码将生成您所描述的所需结果(我使用eXist 3.1.0并在eXide中测试代码):

xquery version "3.1";

import module namespace mem-op="http://maxdewpoint.blogspot.com/memory-operations" at 
    "/db/apps/XQuery-XML-Memory-Operations-master/memory-operations-pure-xquery.xqy";

let $content := 
    <items>
        <item1>A</item1>
        <item2>B</item2>
        <itemlist>
            <item3>C</item3>
        </itemlist>
    </items>
let $copy := mem-op:copy($content)
let $insert := mem-op:insert-child($copy, $content/itemlist, element item3 {"D"})
return
    mem-op:execute($insert)

返回:

<items>
    <item1>A</item1>
    <item2>B</item2>
    <itemlist>
        <item3>C</item3>
        <item3>D</item3>
    </itemlist>
</items>