Ryan,
This works fine:
let $test := <test><a>hi</a></test>
return mem:node-replace($test/a, <a>there</a>)
=> <test><a>there</a></test>
But if I pluck out a session variable, mem:node-replace has no effect:
(: previously executed
xdmp:set-session-field('test', <test><a>hi</a></test>)
:)
let $test := xdmp:get-session-field('test')
return mem:node-replace($test/a, <a>there</a>)
=> <test><a>hi</a></test>
Why would this work in the first scenario, but not the other? I'm
developing some basic CRUD functionality. Say I've got a
<user><name>eric</name></user> saved in /eric.xml in the DB. I've got
the same user element in my session. To make an update to the nested
name element, here's the commonplace workflow:
- POST new name to an xquery script
- script does an xdmp:node-replace(doc('/eric.xml')/user/name,
<name>blah</name>), which works fine.
- update session variable to reflect the change
It seems I can't just reload the contents of eric.xml into my session
variable, I'm guessing because the change hasn't _really_ taken place
yet (due to the transactional nature of each xquery script, nothing is
actually changed until after the script has executed, correct?).
Instead, I thought I could grab the current user session variable into a
local variable, update it in-memory (with the in-mem-update.xqy module),
and put the new structure back into the session. This doesn't work, for
some reason, as shown above.
The longer I work with xquery, the less feasible it seems to use it in
place of an XCC-enabled java-based website. :(
Eric
Ryan Grimm wrote:
Hi Eric,
The xdmp:node-* functions are intended to be used on nodes that are
stored in the database, that's why you're getting the error about
constructed nodes.
Your work around is fine but I've actually shared a general purpose
library for doing exactly what you're looking to do. You can find it on
the developer site in the commons area at:
http://xqzone.marklogic.com/svn/commons/trunk/memupdate/
The functions are almost identical to the xdmp:node-* functions except
that they return the modified xml back to you which seems like it's
exactly what you're looking for. They also allow you to pass in
multiple nodes to delete or insert instead of just one. I've included
some examples on how to use the library but if you have any questions
let me know.
Bonus answer: If the element isn't in a namespace name(<hi/>) will work,
otherwise you can use local-name(<x:hi/>) and it will return "hi".
--Ryan
On Sep 15, 2008, at 10:26 AM, Eric Palmitesta wrote:
Hi all,
I'd like a function to add an attribute to an input element and return
it. I realize that xquery is functional, and the returned element
will be a new element rather than a modified version of the input
element, which is fine.
Consider the following function:
---
define function f($x as element(test))
as element(test)
{
xdmp:node-insert-child($x, attribute new { "new" } )
}
let $x := <test blah="blah">some text</test>
return f($x)
=> Error: Cannot update constructed nodes
---
This errors out and tells me "Cannot update constructed nodes", as
indicated in the API docs ("On-the-fly constructed nodes cannot be
updated.",
http://developer.marklogic.com/pubs/3.2/apidocs/UpdateBuiltins.html#node-insert-child)
Here's a workaround function:
---
define function g($x as element(test))
as element(test)
{
<test>{
$x/text(),
$x/child::*,
$x/attribute::*,
attribute new{ "new" }
}</test>
}
let $x := <test blah="blah">some text</test>
return g($x)
=> <test blah="blah" new="new">some text</test>
---
It works. Is there a better way though? Also, what's the point of
xdmp:node-insert-child if it can't operate on an argument to a
function? Why is the arg considered 'on-the-fly'? Shouldn't the
function not care where $x came from or how it was constructed?
Bonus question: If I have an $x as element(), how can I pull out the
element name? IE if $x := <hi />, I want "hi".
Cheers,
Eric
_______________________________________________
General mailing list
[email protected]
http://xqzone.com/mailman/listinfo/general
_______________________________________________
General mailing list
[email protected]
http://xqzone.com/mailman/listinfo/general
_______________________________________________
General mailing list
[email protected]
http://xqzone.com/mailman/listinfo/general