XQuery函数库组织

时间:2018-07-31 16:24:11

标签: xquery marklogic

通常,当我在XSLT中工作时,我会创建一个主要由导入组成的主文件。我将每个导入文件都保持较小,以便于维护。

我正在尝试在XQuery(在MarkLogic中)中做同样的事情,但是我无法使其按我希望的那样工作。

这就是我想要做的:

main.xqy:

xquery version "1.0-ml";
module namespace summit = "http://example.com/summit";
import module "http://example.com/summit" at "/ext/variables.xqy";
import module "http://example.com/summit" at "/ext/utils.xqy";

variables.xqy:

xquery version "1.0-ml";
module namespace summit = "http://example.com/summit";
declare variable $BASEURL as xs:string  := "https://example.com/v1";

utils.xqy:

xquery version "1.0-ml";
module namespace summit = "http://example.com/summit";
declare function summit:baseUrl() {
    let $url := $BASEURL
    return $url
};

,然后使用以下代码在查询控制台中调用它:

xquery version "1.0-ml";
import module namespace summit = "http://example.com/summit" at "/ext/main.xqy";
summit:baseUrl()

我收到以下错误:

[1.0-ml] XDMP-UNDVAR: (err:XPST0008) Undefined variable $BASEURL
Stack Trace
In /ext/utils.xqy on line 4
In xdmp:eval("xquery version &quot;1.0-ml&quot;;&#10;import module namespace s...", (), <options xmlns="xdmp:eval"><database>8148014817830251656</database>...</options>)

对于以相同方式定义的函数(在一个xquery文件中定义,在导入到main.xqy中的另一个文件中使用)定义的函数,我也会遇到类似的错误。

我可以通过将variable.xqy导入utils.xqy来解决此问题,但是我想避免这种情况,因为它增加了管理开销,而不是减少了管理开销。

我确定这里确实有我做错的事情,但是我不确定是什么。

您如何组织大型xquery项目?

2 个答案:

答案 0 :(得分:6)

与XSLT不同,XQuery的设计宗旨是使模块可以独立编译,这意味着模块不能依赖于(通过传递)自己的模块导入无法访问的变量或函数。

尽管有时这可能会带来不便,但它的确具有使库模块更可重用的好处,因为它们没有隐藏的依赖关系,这意味着可以将它们导入一个主模块,而不能导入另一个主模块。

请注意,这里有一些微妙之处。首先,该规范指出,如果两次导入同一模块,则只会得到一个变量副本:

如果查询通过多个路径导入同一模块,则仅导入该模块的一个实例。由于仅导入模块的一个实例,因此模块序言中声明的每个变量只有一个实例。

但是它也注意到“相同模块”的概念在边缘是模糊的:

当多次在同一“导入模块”声明中或同一查询中的不同“导入模块”声明中多次使用同一绝对位置URI时,包含该模块的资源的单个副本为已加载。使用不同的绝对位置URI时,除非实现能够确定不同的URI是对同一资源的引用,否则每个结果都会导致加载单个模块。只要在每种情况下绝对位置URI相同,多次导入同一模块就不会由于重复的变量或函数名称而引起错误。

答案 1 :(得分:5)

您的utils.xqy需要导入变量。xqy。

您可以尝试以下方法:

xquery version "1.0-ml";
module namespace summit = "http://example.com/summit";
import module namespace variables = "http://example.com/summit" at "/ext/variables.xqy";
declare function summit:baseUrl() {
    let $url := $variables:BASEURL
    return $url
};

除了更正此问题外,您的代码组织也类似于我的首选技术。