Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

updating multiple nodes in xml with xquery and xdmp:node-replace

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?

like image 818
morja Avatar asked Mar 14 '26 10:03

morja


1 Answers

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

like image 73
morja Avatar answered Mar 17 '26 03:03

morja



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!