XQuery 函数库组织
XQuery function library organization
通常,当我在 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 "1.0-ml"; import module namespace s...", (), <options xmlns="xdmp:eval"><database>8148014817830251656</database>...</options>)
对于以相同方式定义的函数(在一个 xquery 文件中定义,在导入到 main.xqy 的另一个文件中使用),我得到了类似的错误。
我可以通过将 variables.xqy 导入 utils.xqy 来解决这个问题,但我想避免这种情况,因为它会增加而不是减少管理开销。
我确定我在这里做错了什么,但我不确定是什么。
您如何组织大型 xquery 项目?
您的 utils.xqy 需要导入 variables.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
};
除了更正此问题外,您的代码组织也类似于我的首选技术。
与 XSLT 不同,XQuery 的设计使得模块可以独立编译,这意味着模块不能依赖于通过其自己的模块导入(传递)无法访问的变量或函数。
虽然这有时会带来不便,但它确实有利于使库模块更易于重用,因为它们没有隐藏的依赖关系,这意味着它们可以导入一个主模块而不是另一个主模块。
注意这里有一些微妙之处。首先,规范指出,如果你两次导入同一个模块,你只会得到一个变量副本:
如果查询通过多个路径导入同一个模块,则只会导入该模块的一个实例。因为只有一个模块的实例被导入,所以在模块的序言中声明的每个变量只有一个实例。
但它也指出 "same module" 的概念在边缘处是模糊的:
当同一个绝对位置 URI 多次使用时,无论是在同一个 "import module" 声明中还是在同一个查询中的不同 "import module" 声明中,单个副本加载包含模块的资源。当使用不同的绝对位置 URI 时,每个 URI 都会导致加载单个模块,除非实现能够确定不同的 URI 是对同一资源的引用。只要绝对位置 URI 在每种情况下都相同,就不会因重复的变量或函数名称而出现错误。
通常,当我在 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 "1.0-ml"; import module namespace s...", (), <options xmlns="xdmp:eval"><database>8148014817830251656</database>...</options>)
对于以相同方式定义的函数(在一个 xquery 文件中定义,在导入到 main.xqy 的另一个文件中使用),我得到了类似的错误。
我可以通过将 variables.xqy 导入 utils.xqy 来解决这个问题,但我想避免这种情况,因为它会增加而不是减少管理开销。
我确定我在这里做错了什么,但我不确定是什么。
您如何组织大型 xquery 项目?
您的 utils.xqy 需要导入 variables.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
};
除了更正此问题外,您的代码组织也类似于我的首选技术。
与 XSLT 不同,XQuery 的设计使得模块可以独立编译,这意味着模块不能依赖于通过其自己的模块导入(传递)无法访问的变量或函数。
虽然这有时会带来不便,但它确实有利于使库模块更易于重用,因为它们没有隐藏的依赖关系,这意味着它们可以导入一个主模块而不是另一个主模块。
注意这里有一些微妙之处。首先,规范指出,如果你两次导入同一个模块,你只会得到一个变量副本:
如果查询通过多个路径导入同一个模块,则只会导入该模块的一个实例。因为只有一个模块的实例被导入,所以在模块的序言中声明的每个变量只有一个实例。
但它也指出 "same module" 的概念在边缘处是模糊的:
当同一个绝对位置 URI 多次使用时,无论是在同一个 "import module" 声明中还是在同一个查询中的不同 "import module" 声明中,单个副本加载包含模块的资源。当使用不同的绝对位置 URI 时,每个 URI 都会导致加载单个模块,除非实现能够确定不同的 URI 是对同一资源的引用。只要绝对位置 URI 在每种情况下都相同,就不会因重复的变量或函数名称而出现错误。