为了模拟 XQuery 更新中的自动增量值,假设首次运行时<root count="0"/>
,以下方法工作正常:
let $count := /root/@count
return (
insert node <node id='{ $count }'/> into /root,
replace value of node $count with $count + 1
)
。很好地屈服:
<root count="1">
<node id="0">
</root>
但是,我想在我的 Java 代码中定义节点,然后将其绑定为org.w3c.dom.Node
或Document
,甚至String
。喜欢:
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();
但是,这只会让我在属性中{ $count }
文本。将节点绑定为xs:string
值具有相同的效果。
当然,这是一个很好的防止"XQuery注入"的保护。仍然如此:有没有办法使 XQuery 更新过程成为我在变量本身中的封闭表达式?
(在 XQuery 中使用自动增量值的任何其他聪明想法也非常受欢迎,但是请参阅使用 XQuery 更新自动递增?
XQuery Update 的转换表达式可能会在这里为您提供帮助。它可用于修改主内存中的现有节点。您的示例可以重写如下:
declare variable $n external;
let $count := /root/@count
let $n :=
copy $c := $n
modify replace value of node $c/node/@id with $count
return $c
return (
insert node $n into /root,
replace value of node $count with $count + 1
)
外部节点$n
复制到变量 $c
中,并将根节点的 @id
属性替换为当前值 $count
。
当然,这种方法有很多变体。例如,您可以插入一个新的@id
属性而不是替换虚拟人。
copy $c := $n
modify insert node attribute id { $count } into $c/node
return $c
转换表达式的当前语法是需要首先习惯的东西。更好的可读语法可能会受到官方规范的未来版本的约束。
说到注射...为什么不直接将节点作为字符串传递并使用basex:eval()?
String node = "<node id='{ $count }'/>";
String expr =
...
+ " insert node xquery:eval($n) into /root, "
...
上面,xquery:
指的是 BaseX 模块。