This XQuery update related question might be not the most BaseX-specific question that has ever been asked on the list, but anyway:
I’m currently improving the performance of sxedit (that I presented at XML Prague yesterday). One nasty workaround that I have to do in the browser is escaping the names of the TEI elements body and head when I generate TEI XML from HTML despite the fact that these elemens are in a different namespace (because browsers…). So I have TEI XML with the elements _____head and _____body. I serialize this XML and use regex replacement on the string when I submit the TEI XML for download or for storage in BaseX. (Yes, it seems silly to serialize the XML before POSTing it to RESTXQ and then using parse-xml(), but don’t mind that for the moment.)
The function that does the storage is at https://github.com/gimsieke/sxedit/blob/master/lib/basex/restxq/sxedit.xqm#L...
Now I thought that I might do without the performance-killing string replacement in the browser if I let BaseX transform the posted data prior to replacing the stored subtree with what was posted.
So I tried the following for the function body:
copy $doc := parse-xml($wrapper) modify ( for $n in $doc/descendant-or-self::*[starts-with(local-name(), '_____')] let $repl := replace(local-name($n), '^_____', ''), $uri := namespace-uri($n) return rename node $n as QName($uri, $repl) ) return replace node db:open($doc/*:frag/@db, $doc/*:frag/@doc)//*[path() eq $doc/*:frag/@xpath] with $doc/*:frag/*
upon which I get: [XUST0001] Transform expression: no updating expression allowed.
How would I achieve the transform and then update operation?
Gerrit
Hi Gerrit,
the return clause of the transform (copy) expression does not allow update operations. What you can do is to wrap your code in a FLWOR expression:
let $doc := copy $doc := parse-xml($wrapper) modify ( for $n in $doc/descendant-or-self::*[starts-with(local-name(), '_____')] let $repl := replace(local-name($n), '^_____', ''), $uri := namespace-uri($n) return rename node $n as QName($uri, $repl) ) return $doc return replace node db:open($doc/*:frag/@db, $doc/*:frag/@doc)//*[path() eq $doc/*:frag/@xpath] with $doc/*:frag/*
You can also use the (for now BaseX-specific) "update" keyword, e. g. as follows:
let $doc := parse-xml($wrapper) update ( for $n in descendant-or-self::*[starts-with(local-name(), '_____')] let $repl := replace(local-name($n), '^_____', ''), $uri := namespace-uri($n) return rename node $n as QName($uri, $repl) ) return replace node db:open($doc/*:frag/@db, $doc/*:frag/@doc)//*[path() eq $doc/*:frag/@xpath] with $doc/*:frag/*
Hope this helps, Christian
Christian, thanks for your XQuery support. Will pay back in XSLT support ;)
I made this change, and I also made the xquery:eval statements compatible with 7.8: https://github.com/gimsieke/sxedit/blob/master/lib/basex/restxq/sxedit.xqm
Gerrit
On 16.02.2014 15:40, Christian Grün wrote:
Hi Gerrit,
the return clause of the transform (copy) expression does not allow update operations. What you can do is to wrap your code in a FLWOR expression:
let $doc := copy $doc := parse-xml($wrapper) modify ( for $n in $doc/descendant-or-self::*[starts-with(local-name(), '_____')] let $repl := replace(local-name($n), '^_____', ''), $uri := namespace-uri($n) return rename node $n as QName($uri, $repl) ) return $doc return replace node db:open($doc/*:frag/@db, $doc/*:frag/@doc)//*[path() eq $doc/*:frag/@xpath] with $doc/*:frag/*
You can also use the (for now BaseX-specific) "update" keyword, e. g. as follows:
let $doc := parse-xml($wrapper) update ( for $n in descendant-or-self::*[starts-with(local-name(), '_____')] let $repl := replace(local-name($n), '^_____', ''), $uri := namespace-uri($n) return rename node $n as QName($uri, $repl) ) return replace node db:open($doc/*:frag/@db, $doc/*:frag/@doc)//*[path() eq $doc/*:frag/@xpath] with $doc/*:frag/*
Hope this helps, Christian
basex-talk@mailman.uni-konstanz.de