在 BaseX 中使用 XQuery XQUF 获取无更新表达式错误,以便在一个函数中进行 unknown/variable 次更新

Getting no updating expression error using XQuery XQUF in BaseX to make an unknown/variable number of updates in one function

由于技术上没有 "updating expression",此代码已停止执行 - 可能是因为它隐藏在 eval 字符串中,解释器看不到它。

我查看过的使用 xquery 更新工具的示例具有固定数量的更新语句,但我想在更新函数中处理可变数量的更新语句。

我可能偏离了(如果我是的话请告诉我)我是如何接近这个解决方案的,但我试图创建一个字符串,所有更新语句都以逗号分隔,然后 xquery:eval 字符串到在一个 return 语句中完成所有更新。

我认为这应该可行,因为该字符串看起来像如果我知道有多少我会硬编码的语句。
例如 return(将节点数量的值替换为'1', 将节点市场的价值替换为 'new_market')

Stopped at C:/Program Files (x86)/BaseX/webapp/product.xqm, 109/7:
[XUST0002] Function body is no an updating expression. 
(looks like a typo in the error message btw)

(: example new data values 
   $req - could be any number of nodes with new values
<request>
  <data>
    <ID>1</ID>
    <quantity>1</quantity>
    <market>new_market</market>
  </data>
</request>
:)

(:  Old data that matches ID and needs replacing
<csv>
  <record>
    <ID>1</ID>
    <quantity>3</quantity>
    <market>old_market</market>
  </record>
<csv>
:)

declare
  %rest:path("updy/{$db}/{$resource}")
  %rest:POST("{$req}")
  %updating function page:updy($db,$resource,$req as document-node()) 
{
let $input := concat("db:open('",$db,"','",$resource,"')") 
for $node_name in $req/request/data/(* except ID)/name()
  let $updating_record := query:eval($input)/csv/record[ID=$req/request/data/ID]
  for $updating_fields in $updating_record//*[name()=$node_name]
    let $to_value := $req/request/data/*[name()=$updating_fields/name()]/data()
    let $eval_string := string-join(concat("replace value of node ",$updating_fields/name()," with '",$to_value,"'")," , ")
return xquery:eval($eval_string))
};

顶部是我试图从休息电话开始工作的代码。底部是我要测试的代码,看看我是否能让它工作。这设置为 return 只是 eval 字符串,然后在那里切换注释以尝试 运行 它。

declare %private updating function local:updy($db,$resource,$req as element()) 
{
  let $input := concat("db:open('",$db,"','",$resource,"')")

  for $node_name in $req//data/(* except ID)/name()
    let $updating_record := xquery:eval($input)/csv/record[ID=$req//data/ID]
    for $updating_fields in $updating_record//*[name()=$node_name]
      let $to_value := $req//data/*[name()=$updating_fields/name()]/data()
      let $eval_string := string-join(concat("replace value of node ",$updating_fields/name()," with '",$to_value,"'")," , ")
  (: return $eval_string :)
  return xquery:eval($eval_string)
};

(: example new data values :)
(: $req - could be any number of nodes with new values :)
let $req := 
<request>
  <data>
    <ID>1</ID>
    <quantity>1</quantity>
    <market>new_market</market>
  </data>
</request>

(:  Old data that matches ID and needs replacing :)
let $input := 
<csv>
  <record>
    <ID>1</ID>
    <quantity>3</quantity>
    <market>old_market</market>
  </record>
</csv>
let $dbadd := db:create("ProductTest", $input, "exportDataTest.csv") 
return local:updy("ProductTest","exportDataTest.csv",$req)

我在下面添加完成的代码,因为在我在这里收到的帮助下,我能够让它正常工作。

declare
  %rest:path("updz/{$db}/{$resource}")
  %rest:POST("{$req}")
  %updating function page:updz($db,$resource, $req as document-node()) {
    let $input := concat("db:open('",$db,"','",$resource,"')")
    let $the_id := $req//data/ID
    let $update_string := 
      for $node_name in $req//data/(* except ID)/name()
        let $updating_record := xquery:eval($input)/csv/record[ID=$req//data/ID]
        for $updating_fields in $updating_record//*[name()=$node_name]
          let $to_value := $req//data/*[name()=$updating_fields/name()]/data()

    return string-join(concat("replace value of node ", $input,"/csv/record[ID='",$the_id,"']//",$updating_fields/name()," with '",$to_value,"'")," , ")

    let $final_update_string := concat("(",string-join($update_string,","),",update:output(<response><status>1</status></response>))")
    (: return $final_update_string :)
    return xquery:eval-update($final_update_string)
};      

错误消息的原因(带有意外的拼写错误;感谢提示)是包含 xquery:eval 调用的函数被注释为 %updating。然而,xquery:eval 函数是一个非更新函数。

XQuery 更新建议假定每个表达式必须是更新的或只读的。由于 xquery:eval 的参数在查询执行期间可能会发生变化……

for $query in ('123', 'delete node <a/>')
return xquery:eval($query)

…还有第二个函数xquery:eval-update,可用于计算包含更新表达式的查询。如果您知道传入的查询将不会更新,只需删除 %updating 注释即可。

再补充一点:如果在查询中创建数据库,则不能在同一查询中请求其内容(单个 XQuery 是单个事务)。请查看 Pending Update List or have a look into the full specification.

上的简短文档