令我惊讶的是,我正在努力解决一个非常基本的XQuery问题,即在主XQuery模块和导入的库模块之间共享全局变量的正确方法是什么。简而言之,我想在某个地方定义一个可以在任何地方重用的全局变量(即在所有(导入的)XQuery模块中),并且我很难找到声明这样一个变量的最佳位置。
假设我有以下主XQuery(test.xq):
import module namespace global="global" at "global.xq";
import module namespace test2="test2" at "test2.xq";
declare variable $test := 'test!';
test2:echo()
此模块导入以下库模块:
global.xq:
module namespace global="global";
declare variable $global:test := 'global!';
test2.xq: module namespace test2 =“test2”;
import module namespace global="global" at "global.xq";
declare function test2:echo() {
$global:test
};
这样可行,但给我留下了一些问题:
这是做到这一点的方法:
?
任何人都可以对此有所了解吗?我想我发现自己挣扎于这个概念的主要原因是因为我已经习惯了eXist的行为,这可能比它应该的要慢。在eXist中,test2.xq模块可以在不导入global.xq模块的情况下引用$ global:test变量:
module namespace test2="test2";
declare namespace global="global";
declare function test2:echo() {
$global:test
};
由于这适用于eXist,但不适用于Saxon,我开始想知道在(导入的)XQuery模块中定义和使用全局变量的正确方法是什么。
亲切的问候,
罗恩
答案 0 :(得分:3)
显然,eXists从XSLT中采用了您可能熟悉的方法。在那里,您还可以通过导入/包含'祖先'模块(在include / import链中更高)引用当前模块外部声明的变量和参数。
据我所知,这不符合XQuery标准!
能够使用它显然非常实用,但有几个很好的理由不这样做。理想情况下,模块是独立的,可重复使用的组件,当它们依赖于这样的外部参数/变量时就不再是这种情况。最好将上下文信息作为参数传递给这些函数。并不总是看起来很优雅,但最终设计得更好。
某些实现提供了使用重定义变量值的替代选项。 MarkLogic有xdmp:set命令,我相信saxon也有变量赋值(或者是XSLT中的那个?)。您可以使用它来“初始化”模块。请注意,虽然模块不是对象,但请尽量避免使用这种方法来保存有状态信息。这也意味着您将依赖于特定于实现的功能。除非您能够使用更新工具。不确定是否打算以这种方式工作..
答案 1 :(得分:1)
在您的实际使用案例中 这些“变量”是什么?顾名思义,它们是否需要能够变化? (如果是这样,将它们放在文档中可能是正确的事情)。如果它们只是常量,那么你给出的方法 - 将它们放在一个模块/命名空间中并根据需要导入它 - 可能是正确的事情。
坦率地说,编写模块以假设其他地方定义的内容,但没有定义其他地方应该存在的内容,让我感到容易发生危险 - 如果没有其他原因,通过使读者更难以遵循流程控制。因此,我有点不清楚为什么这种行为是可取的。
考虑将您的配置封装在文档中,并将该文档作为参数传递给函数调用。