1
votes

I'm trying to wrap a node with another new node using XQuery update and I'm stuck in several different errors let me give you a short example:

Initial XML is

<a id="test">
  <title>title</title>
</a>

XQuery code is:

copy $x := db:open('testdb')/a[@id eq 'test']/title 
modify replace node $x 
with <b>{$x}</b> 
return <ok/>

I'm using basex as the surrounding database and this is why I'm using the db:open function.

What I want to obtain in the end is

<a id="test">
  <b>
    <title>title</title>
  </b>
</a>

But I receive an error:

[XUDY0009] Target has no parent: element title {...}.

Note: the result of query:

db:open('testdb')/a[@id eq 'test']/title

is

<title>title</title>

If I modify the query as follows

copy $x := db:open('testdb')/a[@id eq 'test']/title 
modify replace node db:open('testdb')/a[@id eq 'test']/title
with <b>{$x}</b> 
return <ok/>

then the error is

[XUDY0014] Node was not created by copy clause: element title {...}.

What is the proper way of doing this kind of update queries?

1

1 Answers

3
votes

You need to modify the node that’s bound to $x, and return $x:

copy $a := db:open('testdb')/a[@id eq 'test']
modify replace node $a/title with <b>{ $a/title }</b> 
return $a

In BaseX, the update keyword can be used as alternative. It allows for a more compact representation:

db:open('testdb')/a[@id eq 'test'] update {
  replace node title with <b>{ title }</b> 
}

If you want to update the database node itself, there is no need to use copy or update:

let $title := db:open('testdb')/a[@id eq 'test']/title 
return replace node $title with <b>{ $title }</b>