XQuery 和 Python 之间的根本区别在于 XQuery 是一个函数式编程语言 http://en.wikipedia.org/wiki/Functional_programming。这意味着绑定到变量的值之后无法修改。在你的函数中local:BFS(...)
例如你不能改变的值$queue
在循环内,您所做的就是创建一个新变量$queue
遮蔽了外部。
为了让它工作,您可以将外循环编写为递归函数 http://en.wikipedia.org/wiki/Recursion_%28computer_science%29相反,它将当前队列作为参数。循环的每次迭代都是使用队列的更新版本调用该函数:
declare function local:BFS($graph, $queue, $steps, $end) {
if(empty($queue)) then error(xs:QName('local:NOTFOUND'), 'No path found.')
else (
let $curr := $queue[1], $rest-queue := $queue[position() > 1]
return (
if($curr eq $end) then local:result($steps, $end)
else (
let $successors :=
$graph//node[Links/Link/origin = $curr and not($steps/@to = id)]/id/string()
let $new-steps :=
for $succ in $successors
return <edge from="{$curr}" to="{$succ}" />
return local:BFS(
$graph,
($rest-queue, $successors),
($steps, $new-steps),
$end
)
)
)
)
};
可以通过向起始节点提供第一条边来调用它:
declare function local:BFS($graph, $start, $end) {
local:BFS($graph, $start, <edge to="{$start}" />, $end)
};
所有使用的边都存储在$steps
。为了在找到目的地后重建路径,我们可以向后遍历它们,直到找到初始边缘:
declare function local:result($steps, $dest) {
let $pred := $steps[@to = $dest]/@from/string()
return if(exists($pred)) then (local:result($steps, $pred), $dest)
else $dest
};
如果您担心性能,XQuery 序列可能不是用作队列的最佳数据结构。对于用于查找的 XML 片段也是如此。因此,如果您有权访问XQuery 3.0 http://www.w3.org/TR/xquery-30/处理器,你可以看看我写的一些(至少渐近)更有效的数据结构https://github.com/LeoWoerteler/xq-modules https://github.com/LeoWoerteler/xq-modules。我什至包括迪杰斯特拉算法 https://github.com/LeoWoerteler/xq-modules/blob/master/src/test/xquery/dijkstra.xq举个例子。