Xquery If语句:不完整的FLWOR表达式

Xquery If语句:不完整的FLWOR表达式,xquery,basex,xquery-3.1,Xquery,Basex,Xquery 3.1,我在BaseX编辑器中有以下XQuery代码,但它在if子句中出错,声明 FLWOR表达式不完整:应为“return” 我正在尝试使用的代码: import module namespace functx = 'http://www.functx.com'; declare namespace file = "http://expath.org/ns/file"; let $root := 'E:\basex-index-testing\sonar-small\index' let $ds :

我在BaseX编辑器中有以下XQuery代码,但它在if子句中出错,声明

FLWOR表达式不完整:应为“return”

我正在尝试使用的代码:

import module namespace functx = 'http://www.functx.com';
declare namespace file = "http://expath.org/ns/file";

let $root := 'E:\basex-index-testing\sonar-small\index'
let $ds := file:dir-separator()

(: get files in sonar-small database :)
for $f in db:list('sonar-small')
  (: remove *.xml from doc name :)
  let $corpus := substring($f, 1, string-length($f) - 4)
  for $alpino in db:open('sonar-small', $f)/treebank/alpino_ds
  (: make sure tree has sentence element :)
  where count($alpino/sentence) > 0
      let $sentenceId := data($alpino/@id)

      for $node in $alpino//node
      (: make sure there are less than 500 descendants, 
      less than 100 and more than 0 children :)
      where count($node//node) < 500 and count($node/node) > 0 
            and count($node/node) < 100
        let $catTop := data($node/@cat)

        (: create indexing pattern based on node's direct children :)
        let $childrenRelCat := ()
        for $child in $node/node
          let $childRel := data($child/@rel)
          (: use children's cat or pt attribute, default to '' :)
          let $childCat := data($child/(@cat, @pt, '')[1])
          (: concatenate childrenRelCat sequence (append to list) :)
          let $childrenRelCat := ($childrenRelCat, 
                                  string-join(($childRel, $childCat), '%'))

        let $bf := string-join(functx:sort($childrenRelCat), '_')
        let $sent := <tree id="{$sentenceId}">{$node}</tree>

        let $dir := concat($root, $ds, $catTop)
        (: this if-clause throws an error: missing return statement, 
        incomplete FWLOR:)
        if (file:exists($dir) and file:is-dir($dir))
          then ()
        else file:create-dir($dir)        

        (: append subtree to pattern-file :)
        file:append($dir || $bf || '-index.xml', $sent)
        (: doesn't have to return anything, but FWLOR demands it... :)
        return $f
import模块名称空间functx=”http://www.functx.com';
声明命名空间文件=”http://expath.org/ns/file";
让$root:=“E:\basex索引测试\sonar small\index”
让$ds:=文件:dir-separator()
(:获取声纳小型数据库中的文件:)
以db:list('sonar-small'为单位)表示的$f
(:从文档名称中删除*.xml:)
let$corpus:=子字符串($f,1,字符串长度($f)-4)
对于以db表示的$alpino:open('sonar-small',$f)/treebank/alpino\u ds
(:确保树具有句子元素:)
其中计数($alpino/句)>0
let$sentenceId:=数据($alpino/@id)
对于$alpino//节点中的$node
(:确保子代数少于500,
小于100且子级数超过0:)
其中count($node//node)<500,count($node/node)>0
和计数($node/node)<100
let$catTop:=数据($node/@cat)
(:基于节点的直接子节点创建索引模式:)
let$childrenRelCat:=()
对于$node/node中的$child
let$childRel:=数据($child/@rel)
(:使用儿童的cat或pt属性,默认为“”:)
let$childCat:=数据($child/(@cat,@pt,)[1])
(:连接childrenRelCat序列(附加到列表):)
让$childrenRelCat:=($childrenRelCat,
字符串联接($childRel,$childCat),“%”)
让$bf:=字符串联接(functx:sort($childrenRelCat),“\ux”)
让$sent:={$node}
let$dir:=concat($root,$ds,$catTop)
(:此if子句引发错误:缺少return语句,
不完整的颜色:)
if(文件:exists($dir)和文件:is dir($dir))
然后()
else文件:创建目录($dir)
(:将子树附加到模式文件:)
文件:追加($dir | |$bf | |'-index.xml',$sent)
(:不必返回任何内容,但FWLOR要求它…:)
返回$f
似乎我在XQuery计算表达式或期望表达式排序的方式上遗漏了一些关键的东西。上面的代码有什么错误


(标题几乎相同,但提供的答案没有帮助,因为该操作的代码中存在另一个错误。)

我认为这里真正的问题是您使用的是if表达式

if (file:exists($dir) and file:is-dir($dir))
          then () else file:create-dir($dir) 
为了达到副作用,而不是为了返回结果。虽然像file:create-dir()这样的外部函数可能会有副作用,但这并不是XQuery设计的工作方式,因此您需要非常小心如何使用这些外部函数。不仅如此,关于什么工作和什么不工作的详细规则可能因XQuery处理器而异

此外,当然,您的查询必须满足语法,FLWOR表达式的语法表示它由一系列子句组成,每个子句都是for、let、where、order by、。。。。或返回条款。所以你的“如果”表达是错的

我不知道BaseX,但我认为以下方法可能有效:

let $dir := concat($root, $ds, $catTop)
return (
        if (file:exists($dir) and file:is-dir($dir))
          then ()
          else file:create-dir($dir),        
        file:append($dir || $bf || '-index.xml', $sent),
        $f
)  

let
后面需要一个
返回值
。我不确定你想用整个表达式实现什么,返回5与文件创建有什么关系?@MartinHonnen返回就是一个例子。我经常发现自己身处一个没有任何回报的地方。如果let后面跟着一个return,那么return将退出函数,那么我将如何到达return呢?当您不想返回任何内容时,是否有一种方法可以执行pythonic
return None
?是否允许$dir:='hello/world'返回if(file:exists($dir)和file:is dir($dir)),然后()其他文件:create dir($dir)执行您想要的操作,例如,允许您存储文件名,然后在
if
表达式中使用它?我仍然不确定你想用
返回5
做什么(我还没有检查
文件:create dir
是否返回某些内容)。@MartinHonnen我用我的实际代码替换了伪代码。我添加了一些评论来解释发生了什么。希望这更清楚?现在最后一行已经
return$file
,尽管该变量从未被声明并绑定到一个值。一般来说,问题在于
let
必须始终是带有
返回的
的表达式的一部分,
如果
表达式不能是这样一个FLOWRExpr的初始子句或中间子句,那么它只能放在
return
子句中或在
let
内部使用(例如
let$foo:=if(…)then…else…
)或
用于
(例如,
用于$bar in(如果(…)那么…其他…
)。我可以确认提议的代码将在BaseX中工作。副作用和非确定性函数永远不会被优化掉。在给定的查询中,甚至可以去掉if表达式并始终调用file:create dir(如果目录存在,则不会发生任何事情;如果是文件而不是目录,则无论如何都会出错)。