不允许更新表达式 Basex

No updating expression allowed Basex

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

expression must all be updating or return empty sequence

下面是代码:

declare  %private %updating function local:ingest-job()
{
  
let $contentpath := 'D:19\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>

这里出了什么问题?

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

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

这构建了 results 元素,并且在其中有一个更新函数。 XQUF 规范不允许这样做,并且由于 BaseX 试图符合标准,因此不允许您这样做。

您有多种选择来避免这种情况:

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

这些选项也有描述 within the BaseX wiki

如果您想避免使用自定义 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:19\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>)
       )