4
votes

I am writing code that needs to return a modified version of an XML node, without changing the original node in the parent document.

How can I copy/clone the node so that the original context will not be connected to/affected by it? I don't want changes made to this node to change the original node in the parent document, just to the copy that my function is returning.

What I'm looking for would be very similar to whatever cts:highlight is doing internally:

Returns a copy of the node, replacing any text matching the query with the specified expression. You can use this function to easily highlight any text found in a query. Unlike fn:replace and other XQuery string functions that match literal text, cts:highlight matches every term that matches the search, including stemmed matches or matches with different capitalization. [marklogic docs > cts:highlight]

3

3 Answers

7
votes

The easiest way to create a clone/copy of a node is to use the computed document node constructor:

document{ $doc }

If you are cloning a node that is not a document-node(), and don't want a document-node(), just a clone of the original node(), then you can XPath to select that cloned node from the new document-node():

document{ $foo }/node()
0
votes

Just for completeness: in general, the standard XQuery Update Facility has copy-modify expressions that explicitly perform a copy. With no modifications, this is like explicit cloning.

copy $node := $foo
modify ()
return $node

I am not sure if MarkLogic supports this syntax or not though. As far as I know, it uses its own function library for updates.

0
votes

In-memory XML nodes are not directly modifiable. Instead, you make your desired changes while constructing a new node. If you know XSLT, that can be a good way to do it. If not, you can use an XQuery technique called recursive descent.