morja
morja

Reputation: 8560

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?

Upvotes: 3

Views: 3736

Answers (1)

morja
morja

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

Related Questions