如何在XQuery转换中为JSON格式内容添加节点?
在MarkLogic搜索结果转换中用XQuery添加节点到JSON内容
问题背景
你正在开发MarkLogic REST API的转换函数(用于/v1/search端点),需要给传入的JSON格式$content添加新元素,但使用XQuery编写时,遇到了节点不可变的限制。
你的函数框架:
xquery version "1.0-ml"; module namespace mymodule = "http://marklogic.com/rest-api/transform/mymodule"; declare function mymodule:transform( $context as map:map, $params as map:map, $content as document-node() ) as document-node() { let $new-node := <foo>bar</foo> [...] return $content }
$content的结构(通过xdmp:describe查看):
document{object-node{"snippet-format":text{"mysnippet"}, "total":number-node{1}, "start":number-node{1}, "page-length":number-node{10}, "selected":text{"include"}, "results":array-node{object-node{"index":number-node{1}, "uri":text{"/path/to/file.txt"}}}}}
解决方案
MarkLogic中的节点是不可变的,无法直接修改传入的$content,必须构建包含原内容和新节点的新文档节点。根据输出格式需求,有两种常用方案:
方案1:保持JSON格式,添加新属性
将XML节点转换为JSON键值对,合并到原JSON对象中:
xquery version "1.0-ml"; module namespace mymodule = "http://marklogic.com/rest-api/transform/mymodule"; declare function mymodule:transform( $context as map:map, $params as map:map, $content as document-node() ) as document-node() { let $new-json-entry := map:entry("foo", "bar") let $original-obj := $content/node() // 合并原对象与新属性,生成新的object-node let $new-obj := object-node { map:merge(($original-obj, $new-json-entry)) } return document { $new-obj } }
方案2:输出混合XML格式,包裹原JSON与新节点
如果允许输出为XML,创建一个根节点同时包含原JSON内容和新XML节点:
xquery version "1.0-ml"; module namespace mymodule = "http://marklogic.com/rest-api/transform/mymodule"; declare function mymodule:transform( $context as map:map, $params as map:map, $content as document-node() ) as document-node() { let $new-node := <foo>bar</foo> let $new-root := <search-results> {$content/node()} {$new-node} </search-results> return document { $new-root } }
额外扩展
如果要给results数组添加元素,可以这样操作:
// 提取原结果数组 let $original-results := $original-obj?results/node() // 创建新的结果对象 let $new-result := object-node { "index": 2, "uri": "/path/to/another-file.txt" } // 生成新数组 let $new-results := array-node { ($original-results, $new-result) } // 替换原对象的results属性 let $updated-obj := object-node { map:merge(($original-obj, map:entry("results", $new-results))) }
内容的提问来源于stack exchange,提问作者eaolson
相关产品推荐
相关产品推荐

