1

我正在使用 BaseX 版本 8.6.6 我在更新数据库时遇到错误

表达式必须全部更新或返回空序列

下面是代码:

declare  %private %updating function local:ingest-job()
{

let $contentpath := 'D:\2019\bloomsbury-ingest-content\TEI.zip'
let $archive := file:read-binary($contentpath)
               for $entry in archive:entries($archive)[fn:ends-with(., '.xml')]
               let $rootNode := fn:name(fn:parse-xml(archive:extract-text($archive, $entry))/*)
               return
               let $docId := fn:parse-xml(archive:extract-text($archive, $entry))/*/@xml:id/string()[$rootNode='TEI']
               let $cid := fn:replace($docId,'[a-zA-z-]','')
               let $jobID := fn:concat($cid,'-',fn:string(fn:format-dateTime(fn:current-dateTime(), '[Y0001][M01][D01][H01][m01][s01][f01]')))

              let $jobChunk := <job>
                                  <job-info>
                                      <id>{$jobID}</id>
                                      <cid>{$cid}</cid>
                                  </job-info>
                              </job>
                 return
                 (
                  db:add('testdb',$jobChunk,fn:concat('/jobs/',$jobID,'.xml')),
                db:output( <result><status>Success</status><message>Job created</message><jobid>{$jobID}</jobid></result>)
                  )


};

<results>{local:ingest-job()}</results>

电流输出:

<result>
  <status>Success</status>
  <message>Job created</message>
  <jobid>9781784604387-2019102816303069</jobid>
</result>
<result>
  <status>Success</status>
  <message>Job created</message>
  <jobid>9781784604417-2019102816303069</jobid>
</result>

预期输出:

<results>
<result>
  <status>Success</status>
  <message>Job created</message>
  <jobid>9781784604387-2019102816303069</jobid>
</result>
<result>
  <status>Success</status>
  <message>Job created</message>
  <jobid>9781784604417-2019102816303069</jobid>
</result>
</results>

这里出了什么问题?

4

2 回答 2

2

由于错误消息表明您在此处混合了更新和非更新表达式。您可以通过 using 避免在函数中执行此操作db:output(),但您在主要部分执行此操作:

<results>{local:ingest-job()}</results>

这构造了results元素,并且在其中你有一个更新功能。XQUF 规范不允许这样做,因为 BaseX 试图符合标准,所以不允许这样做。

您有几种选择如何避免这种情况:

  1. 您只能使用转换表达式转换/添加主内存中的节点。
  2. 您只需调用local:ingest-job()而不是<results>{local:ingest-job()}</results>. 这样你就没有非更新表达式。但是,您将没有周围的results元素。
  3. 你打开MIXUPDATES

BaseX wiki中也描述了这些选项。

于 2019-10-29T08:17:24.533 回答
0

如果您想避免使用自定义 MIXUPDATES 选项,一种通用方法是使用您的函数来收集保存所需的所有信息,但将实际执行推迟到您的顶级调用。

对于您的代码,可能类似于:

(: info required to save job for $doc map{jobID, jobChunk} :)
declare  %private function local:ingest-job($doc as document-node()) as map(*)
{
let $docId :=$doc/*/@xml:id/string()[fn:name($doc/*)='TEI']
let $cid := fn:replace($docId,'[a-zA-z-]','')
let $jobID := fn:concat($cid,'-',fn:string(fn:format-dateTime(fn:current-dateTime(), '[Y0001][M01][D01][H01][m01][s01][f01]')))
let $jobChunk := <job>
                  <job-info>
                      <id>{$jobID}</id>
                      <cid>{$cid}</cid>
                  </job-info>
              </job>
 return map{
           jobID: $jobID,
           jobChunk: $jobChunk 
         }
};

let $contentpath := 'D:\2019\bloomsbury-ingest-content\TEI.zip'
let $archive := file:read-binary($contentpath)
let $docs:=archive:entries($archive)[fn:ends-with(., '.xml')]!fn:parse-xml(archive:extract-text($archive, .))

let $jobs:=$docs!local:ingest-job(.)
return (
       $jobs!db:add('testdb', ?jobChunk, fn:concat('/jobs/',?jobID,'.xml')),
       
       update:output(<results>{
           $jobs!<result><status>Success</status><message>Job created</message><jobid>{?jobID}</jobid></result>
         }</results>)
       )
于 2021-11-23T23:05:52.650 回答