Reputation: 8560
I want to update an XML document in my xml database (Marklogic). I have xml as input and want to replace each node that exists in the target xml.
If a node does not exist it would be great if it gets added, but thats maybe another task.
My XML in the database:
<user>
<username>username</username>
<firstname>firstname</firstname>
<lastname>lastname</lastname>
<email>[email protected]</email>
<comment>comment</comment>
</user>
The value of $user_xml:
<user>
<firstname>new firstname</firstname>
<lastname>new lastname</lastname>
</user>
My function so far:
declare function update-user (
$username as xs:string,
$user_xml as node()) as empty-sequence()
{
let $uri := user-uri($username)
return
for $node in $user_xml/user
return
xdmp:node-replace(fn:doc($uri)/user/fn:node-name($node), $node)
};
First of all I cannot iterate over $user_xml/user
. If I try to iterate over $user_xml
I get the exception
arg1 is not of type node()
But maybe its the wrong approach anyway?
Does anybody maybe have sample code how to do this?
Upvotes: 3
Views: 3736
Reputation: 8560
I have to answer it myself:
declare function update-user (
$username as xs:string,
$user_xml as node()) as empty-sequence()
{
let $uri := user-uri($username)
return
for $node in $user_xml/*
let $target := fn:doc($uri)/user/*[fn:name() = fn:name($node)]
return
if($target) then
xdmp:node-replace($target, $node)
else
xdmp:node-insert-child(fn:doc($uri)/user, $node)
};
but maybe someone has a better solution to /user/*[fn:name() = fn:name($node)]
?
Upvotes: 5