我正在尝试从Web表单中更改内存中加载的非常大的XML文件中的几个节点的值.
该文件是这样获得的:
let $file := xdmp:get-request-field("xml_to_upload")
Run Code Online (Sandbox Code Playgroud)
所以,你可以看到文件在内存中.
现在,我需要更改数千个节点的值,到目前为止,我还没能以最佳方式完成它.
有任何想法吗?
到目前为止我尝试过的一些事情:
let $auxVar :=
if($fileStructureIsValid) then
(
for $currentNode in xdmp:unquote($file)//ID
let $log := xdmp:log( fn:concat( "newNodeValue", ": ", mem:replace( $currentNode, element ID{ fn:concat( $subject, "-", fn:data( $currentNode ) ) } ) ) )
return fn:concat( $subject, "-", fn:data( $currentNode ) )
)
else
(
)
Run Code Online (Sandbox Code Playgroud)
mem库是一个自定义下载的库.
如果可能,将文档插入数据库,并在单独的事务中使用 更新节点xdmp:node-replace。
xquery version "1.0-ml";
...
xdmp:document-insert('file.xml', $file) ;
xquery version "1.0-ml";
for $currentNode in doc('file.xml')//ID
return xdmp:node-replace($currentNode,
element ID{ concat($subject, "-", $currentNode) });
Run Code Online (Sandbox Code Playgroud)
或者,如果您必须更新内存中的文档,那么最好只遍历树一次(使更新全部在该操作中),而不是多次mem:replace操作(可能每次都重新遍历树)。
declare function local:update-ids(
$n as item(),
$subject as xs:string
) as item()
{
typeswitch ($n)
case element(ID) return
element ID { concat($subject, "-", $n) }
case element() return
element { node-name($n) } {
@*, $n/node()/local:update-ids(., $subject) }
default return $n
};
let $xml := xdmp:unquote($file)
let $xml-with-updated-ids := local:update-ids($xml, $subject)
...
Run Code Online (Sandbox Code Playgroud)
更新:
正如 Erik 在评论中建议的那样,您还可以在 XSLT 中编写逻辑local:update-ids(使用xdmp:xslt-eval或xdmp:xslt-invoke执行),并且它们在性能方面应该大致相当。事实上,MarkLogic 有一篇关于该主题的博客文章写得非常好:
http://developer.marklogic.com/blog/tired-of-typeswitch
| 归档时间: |
|
| 查看次数: |
939 次 |
| 最近记录: |