Xquery 如何使用xdmp:node-replace()返回完整文档?

Xquery 如何使用xdmp:node-replace()返回完整文档?,xquery,marklogic,Xquery,Marklogic,我有一个要求,在所有流程完成后,我需要最终返回完整的文档 我的上一条语句有一个xdmp:node-replace(),因此它返回一个空序列 在我的最终文档中,这些节点将被替换,但在第一次运行时,我无法在控制台上看到它们。当我第二次运行它时,我可以看到被替换的节点 下面是示例代码- abc.xml---> <root> <id>abcd</id> </root> let $doc := doc("abc.xml") (

我有一个要求,在所有流程完成后,我需要最终返回完整的文档

我的上一条语句有一个
xdmp:node-replace()
,因此它返回一个
空序列

在我的最终文档中,这些节点将被替换,但在第一次运行时,我无法在控制台上看到它们。当我第二次运行它时,我可以看到被替换的节点

下面是示例代码-

abc.xml--->
  <root>
       <id>abcd</id>
  </root>

let $doc := doc("abc.xml")
 (: Let $doc is having an Id node :)

let $replace := xdmp:node-replace($doc//id,<id>1234</id>)
  return $doc

Actual Output-->
 <root>
       <id>abcd</id>
  </root>

 Expected Output-->
   <root>
       <id>1234</id>
  </root>
abc.xml--->
abcd
让$doc:=doc(“abc.xml”)
(:Let$doc有一个Id节点:)
让$replace:=xdmp:node replace($doc//id,1234)
返回$doc
实际输出-->
abcd
预期输出-->
1234
如果我将返回
$replace
,那么它将给我
空序列

我想在第一次运行时返回预期的输出


有什么建议吗?

xdmp:node replace
替换数据库中的节点,而不是内存中的节点。此外,在提交之前,您无法看到数据库更新

一个简单的解决方案是创建一个更新的内存中文档并返回该文档

xquery version "1.0-ml";

xdmp:document-insert("abc.xml",
<root>
  <id>abcd</id>
  <name>Test</name>
</root>
);

let $doc := doc("abc.xml")
let $update := 
<root>
    <id>1234</id>
    {$doc/root/name}
</root>

return (
  xdmp:document-insert("abc.xml", $update), 
  $update
)
xquery版本“1.0-ml”;
xdmp:文档插入(“abc.xml”,
abcd
试验
);
让$doc:=doc(“abc.xml”)
让$update:=
1234
{$doc/root/name}
返回(
xdmp:文档插入(“abc.xml”,$update),
$update
)
编辑:

使用内存内替换功能的备选方案:

xquery version "1.0-ml";

import module namespace mem = "http://xqdev.com/in-mem-update" at '/MarkLogic/appservices/utils/in-mem-update.xqy';

let $doc := doc("abc.xml")
let $updatedDoc := mem:node-replace($doc//id, <id>1234</id>)

return (
  xdmp:node-replace($doc, $updatedDoc),
  $updatedDoc
)
xquery版本“1.0-ml”;
导入模块名称空间mem=”http://xqdev.com/in-mem-update“在mem update.xqy中的'/MarkLogic/appservices/utils/at';
让$doc:=doc(“abc.xml”)
让$updateDoc:=mem:node替换($doc//id,1234)
返回(
xdmp:节点替换($doc,$updatedoc),
$UpdateDoc
)
就性能而言,我认为mine和Mads Hansen的备选方案具有相同的性能特征。我会说选择你最喜欢的。
我在简单的更新用例中使用了我的方法,对于可能还涉及移动节点的更复杂的用例,我更愿意使用Mads Hansen的XSLT替代方案。

您可以使用多语句事务,将写事务与读事务分开,以便可以看到更新

xquery version "1.0-ml";
xdmp:node-replace(doc("abc.xml")//id, <id>1234</id>)
;

xquery version "1.0-ml";
doc("abc.xml")
xquery版本“1.0-ml”;
xdmp:node replace(doc(“abc.xml”)//id,1234)
;
xquery版本“1.0-ml”;
文档(“abc.xml”)

另一种在内存中修改的替代方法是通过XSLT。使用标识转换,创建模板以匹配要更改的节点:

xquery version "1.0-ml";
declare variable $XSLT := 
  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="id/text()">
        <xsl:text>1234</xsl:text>
    </xsl:template>

  </xsl:stylesheet>;

let $doc := doc("abc.xml")
let $modified := xdmp:xslt-eval($XSLT, $doc)
return 
  ( xdmp:node-replace($doc, $modified), $modified )
xquery版本“1.0-ml”;
声明变量$XSLT:=
1234
;
让$doc:=doc(“abc.xml”)
让$modified:=xdmp:xslt eval($xslt,$doc)
返回
(xdmp:节点替换($doc,$modified),$modified)

这个答案基本上是正确的。xdmp:node-replace()是一个不返回任何内容的状态设置函数。因此,这个答案相当于
让$doc:=doc(“abc.xml”)返回xdmp:node replace($doc//id,1234)
,然后在新事务中,
doc(“abc.xml”)
来查看更改的doc@Wargner迈克尔——谢谢你,这对我有帮助。所以基本上,在任何
节点操作期间,只要我想返回文档结构,我就可以返回
mem
文档?它不会产生性能问题?我认为返回内存中的文档没有问题。此外,这不应产生任何性能问题。将我的答案编辑为您可能想使用的另一个选项。@WagnerMichael谢谢!这很有帮助:)当我尝试使用分号
它给了我
意外的标记语法错误
并询问-你是说逗号
否,a
。听起来你可能有一个太多的地方。您是否正在运行我发布的代码,或者您是否已应用到另一个可能有附加
的模块
某处?@Mads——我正在将其应用于我的一个XQuery模块,但它没有任何
除了在顶部声明
变量
导入
名称空间之外。它说我们不能使用
XQuery中的运算符以终止一行