在使用 eXist-db 和 XQuery 存储数据之前更新内存中的节点
Update in-memory nodes before storing the data with eXist-db and XQuery
我正在使用 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]
不知道该怎么办。我还尝试在存储文档后加载文档并在此处插入节点集,这样我就不会更改内存中的数据,但这也不起作用。未插入节点集。
您说得对,eXist 的 XQuery 更新工具不支持内存操作。除了身份转换(例如,使用 XSLT 或 a recursive application of XQuery's typeswitch expression,您找到的 Ryan J. Dew 库的 "pure xquery" 版本是一个可行的选择。
假设您已经下载了 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)
这个returns:
<items>
<item1>A</item1>
<item2>B</item2>
<itemlist>
<item3>C</item3>
<item3>D</item3>
</itemlist>
</items>
我正在使用 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]
不知道该怎么办。我还尝试在存储文档后加载文档并在此处插入节点集,这样我就不会更改内存中的数据,但这也不起作用。未插入节点集。
您说得对,eXist 的 XQuery 更新工具不支持内存操作。除了身份转换(例如,使用 XSLT 或 a recursive application of XQuery's typeswitch expression,您找到的 Ryan J. Dew 库的 "pure xquery" 版本是一个可行的选择。
假设您已经下载了 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)
这个returns:
<items>
<item1>A</item1>
<item2>B</item2>
<itemlist>
<item3>C</item3>
<item3>D</item3>
</itemlist>
</items>