4

I have an xml document as follows

<users>
  <user test="oldvalue">
   <userid>sony</userid>
   <name>vijay</name>
  </user>
</users>

I am trying to write an xquery to 1) find the user with the given userid - sony 2) change the value of the "test" attribute of the given user to "newvalue".

I am trying the following: (where doc_name = name of the xml document, userid = sony)

declare variable $doc_name as xs:string external;
declare variable $userid as xs:string external;
let $users_doc := doc($doc_name)/users

let $old := $users_doc/user[userid=$userid]/@test="oldvalue"
let $new := $users_doc/user[userid=$userid]/@test="newvalue"

return replace node $old with $new

I see the following error: [XUTY0008] Single element, text, attribute, comment or pi expected as replace target.

How do I fix this?

John
  • 2,820
  • 3
  • 30
  • 50
sony
  • 1,557
  • 10
  • 36
  • 50

2 Answers2

5

You wrote:

let $old := $users_doc/user[userid=$userid]/@trusted="oldvalue" 

So, $old holds the result for that node set comparison.

You need:

declare variable $doc_name as xs:string external; 
declare variable $userid as xs:string external; 
let $users_doc := doc($doc_name)/users 

    let $old := $users_doc/user[userid=$userid]/@test
    let $new := 'newvalue' 

return replace value of node $old with $new 

Edit: I think is better to use replace value of in this case.

  • let $old := $users_doc/user[userid=$userid]/@test let $new := $users_doc/user[userid=$userid]/@test{'newvalue'} return replace node $old with $new is leading to the error: [XPST0003] Expecting 'where', 'order' or 'return' expression. I also tried return replace attribute $old with $new. Note that the xml document may have multiple users each with a test attribute. – sony Nov 12 '10 at 20:58
  • let $new := attribute test {'newvalue'} - I am not sure what this would refer to. What is the attribute test here ? There would be multiple test attributes in one document given that there would be multiple users. Do you mean $new := $users_doc/user[userid=$userid]/@test{'newvalue'}. I am not sure what you edited. – sony Nov 12 '10 at 22:39
  • I see a different error now: [XUDY0027] Replace target must not be empty. What I am guessing is $old now contains the attribute(test) but not the value of the attribute('oldvalue'). I guess I need to replace the text child/value of the attribute with $new as against replacing the node with a string. But, I am not sure how to do this. – sony Nov 12 '10 at 23:14
  • @sony: "Replace target must not be empty": This means that `$users_doc/user[userid=$userid]/@test` is not selecting anything. So, `$users_doc` is empty or your input sample doesn't match your actual input so `user[userid=$userid]/@test` part it's not correct. –  Nov 13 '10 at 13:43
2
let $old := $users_doc/user[userid=$userid]/@test="oldvalue"

let $new := $users_doc/user[userid=$userid]/@test="newvalue"

return replace node $old with $new

The type of $old is xs:boolean -- not a node type. Therefore, the error message you get is correct.

You want:

let $old := $users_doc/user[userid=$userid]/@test[.="oldvalue"]

BTW: There is no replace operator in the standard XQuery.

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431