To mimic an auto-increment value in XQuery Update, the following works fine, assuming <root count="0"/>
when running this for the first time:
let $count := /root/@count
return (
insert node <node id='{ $count }'/> into /root,
replace value of node $count with $count + 1
)
...nicely yielding:
<root count="1">
<node id="0">
</root>
However, I'd like to define the node in my Java code, and then bind that as an org.w3c.dom.Node
or Document
, or even String
. Like:
String expr =
" declare variable $n external; "
+ " let $count := /root/@count; "
+ " return ( "
+ " insert node $n into /root, "
+ " replace value of node $count with $count + 1 "
+ " ) ";
XQConnection xqc = ...;
XQPreparedExpression xqp = xqc.prepareExpression(expr);
// org.w3c.dom.Node node is <node id='{ $count }'/>
xqp.bindNode(new QName("n"), node, null);
xqp.executeQuery();
However, this just leaves me the text { $count }
in the attribute. Binding the node as an xs:string
value has the same effect.
Of course, this is a nice protection against "XQuery injection". Still then: is there any way to make XQuery Update process an enclosed expression I have in the variables themselves?
(Any other smart ideas to use auto-increment values in XQuery are very welcome too, but then see Auto increment with XQuery Update?)
Speaking of injection...why not just pass the node as a string and use basex:eval()?
Above,
xquery:
refers to a BaseX module.The transform expression of XQuery Update may help you here. It can be used to modify existing nodes in main memory. Your example could be rewritten as follows:
The external node
$n
is copied to the variable$c
, and the@id
attribute of the root node is replaced with the current value of$count
.Of course there are many variants to this approach. You could e.g. insert a new
@id
attribute instead of replacing the dummy..The current syntax of the transform expression is something one needs to get used to first. A better readable syntax may be subject to future versions of the official spec.