Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doing a xdmp:node-replace() for a sequence of elements and replace that with one element

So I have an interesting problem, assume I have this document (example.xml) inside a MarkLogic database:

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

I want to replace all the "Active" Enroll elements with one node, so essentially my end result for this should be:

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

To get this done, this is the code I wrote:

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

But this is the result I get:

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

The code replaces each active enroll with the same node I specified to replace. I want it to replace both the nodes at the same time with only one node. How can I do that and get the result I want?

like image 780
Andy Chan Avatar asked Nov 26 '25 21:11

Andy Chan


1 Answers

Consider doing a xdmp:node-delete on the active ones, and a separate xdmp:node-insert-child on the parent.

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

Or do a xdmp:node-replace on the first, and xdmp:node-delete's on the others. You should be able to do all that in one request, so it would be just one commit.

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

You could also rebuild the parent node, and replace that in its entirety. That might be easier to reason with, and would likely be similar in performance.

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>)
like image 182
grtjn Avatar answered Nov 28 '25 16:11

grtjn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!