首页 > 解决方案 > 对一系列元素执行 xdmp:node-replace() 并将其替换为一个元素

问题描述

所以我有一个有趣的问题,假设我在 MarkLogic 数据库中有这个文档(example.xml):

<Enrolls>
  <Enroll>
    <Status> Active </Status>
    <boom> boom2 </boom>
  </Enroll>
    <Enroll>
    <Status> Active </Status>
    <boom> boom </boom>
  </Enroll>
  <Enroll>
    <Status> Inactive </Status>
    <boom> boom </boom>
  </Enroll>
</Enrolls>

我想用一个节点替换所有“活动”注册元素,所以基本上我的最终结果应该是:

<Enrolls>
  <boom> boom for the actives </boom>
  <Enroll>
    <Status> Inactive </Status>
    <boom> boom </boom>
  </Enroll>
</Enrolls>

为了完成这个,这是我写的代码:

xdmp:node-replace((doc("example.xml")/Enrolls/Enroll[Status eq " Active "]), <boom> boom for the actives </boom>)

但这是我得到的结果:

<Enrolls>
  <boom> boom for the actives </boom>
  <boom> boom for the actives </boom>
  <Enroll>
    <Status> Inactive </Status>
    <boom> boom </boom>
  </Enroll>
</Enrolls>

该代码用我指定要替换的相同节点替换每个活动注册。我希望它只用一个节点同时替换两个节点。我怎样才能做到这一点并得到我想要的结果?

标签: xquerymarklogic-9

解决方案


考虑对活动的做一个,对父母做xdmp:node-delete一个单独的。xdmp:node-insert-child

for $active in doc("example.xml")/Enrolls/Enroll[Status eq " Active "]
return 
  if ($active/following-sibling::Enroll[Status eq " Active "])
  then xdmp:node-delete($active)
  else xdmp:node-replace($active, <boom> boom for the actives </boom>)

或者xdmp:node-replace在第一个上做 a ,然后xdmp:node-delete在其他上做。您应该能够在一个请求中完成所有这些操作,因此只需一次提交。

let $enrolls := doc("example.xml")/Enrolls
return ( 
  $enrolls/Enroll[Status eq " Active "]/xdmp:node-delete(.),
  xdmp:node-insert-child($enrolls, <boom> boom for the actives </boom>)
)

您还可以重建父节点,并完全替换它。这可能更容易推理,并且可能在性能上相似。

let $enrolls := doc("example.xml")/Enrolls
return 
  xdmp:node-replace($enrolls, 
    <Enrolls>
      <boom> boom for the actives </boom>
      {$enrolls/* except $enrolls/Enroll[Status eq " Active "]}
    </Enrolls>)

推荐阅读