使用BaseX中的XQuery XQUF在一个函数中创建未知/可变数量的更新时,不会更新表达式错误

时间:2018-05-28 16:53:31

标签: xquery updating basex

此代码在其轨道中停止,因为技术上没有"更新表达式" - 可能是因为它隐藏在一个eval字符串中,并且解释器没有看到它。

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

我可能会离开(请告诉我,如果我)我如何处理此解决方案,但我尝试创建一个字符串,所有更新语句以逗号分隔,然后xquery:eval字符串以执行所有操作一个返回语句中的更新。

我认为这应该有效,因为字符串看起来像我会硬编码的语句,如果我知道多少 例如 返回(用' 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))
};

顶部是我试图通过休息呼叫工作的代码。底部是我试图测试的代码,看看我是否可以让它工作。这被设置为仅返回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)
};      

1 个答案:

答案 0 :(得分:1)

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

XQuery Update Recommendation假定每个表达式必须是更新或只读。由于xquery:eval的参数在查询执行期间可能会有所不同......

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

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

还有一条评论:如果在查询中创建数据库,则无法在同一查询中请求其内容(单个XQuery是单个事务)。请查看Pending Update List上的简短文档,或查看full specification