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

How to return the full document using xdmp:node-replace()?

我有一个要求,我需要在所有过程完成后最后 return 完整的文档。

我最后的声明有一个 xdmp:node-replace(),因此它是 returning 一个 empty sequence

我的最终文档中的节点正在被替换,但我无法在 1st 运行 的控制台上看到它们。当我 运行 第二次使用它时,我可以看到被替换的节点。

这里是示例代码-

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>

如果我愿意 return $replace 那么它会给我 empty sequence

我想 return 1st 的预期输出 运行

有什么建议吗?

xdmp:node-replace 替换数据库中的节点,而不是内存中的节点。您也看不到提交前的数据库更新。

一个简单的解决方案是创建一个更新的内存中文档,然后return。

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 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
)

在性能方面,我认为我的和 Mads Hansen 的替代品具有相同的性能特征。我会说选择你最喜欢的。 我已经将我的方法用于简单的更新用例很多,对于可能还涉及移动节点的更复杂的用例,我宁愿使用 Mads Hansen 的 XSLT 替代方案。

可以使用多语句事务,using a semi-colon把写事务和读事务分开,这样就可以看到更新了。

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

xquery version "1.0-ml";
doc("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 )