I want to delete multiple nodes from document using a loop and hold the updated doc in memory using in-memory-update api. Below is the code I am using:
var mem = require("/MarkLogic/appservices/utils/in-mem-update.xqy");
var myDoc = cts.doc("abc.xml");
var nodeArr = [];
nodeArr = myDoc.xpath("/document/version").toArray();
for (i in nodeArr)
{
if(nodeArr[i].xpath('@id')!= "1"){
myDoc = mem.nodeDelete(nodeArr[i])
}
}
myDoc;
Let's say I have 3 versions in my document and I want to delete versions other than id=1
. Result of below code is only deleting version 3 and keeping version 2 still in the document. Maybe version 2 deletion is overridden by version 3 in memory.
What am I missing here?
This solution works:
var mem = require("/MarkLogic/appservices/utils/in-mem-update.xqy");
var myDoc = cts.doc("abc.xml");
var nodeArr = [];
var track = [];
nodeArr = myDoc.xpath("/document/version").toArray();
for (i in nodeArr)
{
if(nodeArr[i].xpath('@id')!= "1"){
track.push(nodeArr[i]);
}
}
myDoc = mem.nodeDelete(Sequence.from(track));
myDoc;
The problem is that mem.nodeDelete only deletes the node from the state of the document as it was as the time the node was instantiated. Think of it as if a copy of the document is made in memory and you're only deleting the node from that node's unique copy. The work around to this is to make sure you delete all nodes from the same copy. It's a bit confusing but hopefully this code helps clarify the application of it.
Edit, Here is an alternative that should work on MarkLogic 8 as well as 9:
var mem = require("/MarkLogic/appservices/utils/in-mem-update.xqy");
var myDoc = cts.doc("abc.xml");
var id = 0;
for (i in myDoc.xpath("/document/version").toArray())
{
var nodeArr = myDoc.xpath("/document/version").toArray()[id];
if(nodeArr.xpath('@id')!= "1"){
myDoc = mem.nodeDelete(nodeArr);
}
else id++;
}
myDoc;