XQuery:跨(导入)模块共享全局变量

时间:2012-03-06 13:28:58

标签: module global-variables xquery

令我惊讶的是,我正在努力解决一个非常基本的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
    };
    

这样可行,但给我留下了一些问题:

  • 这是做到这一点的方法:

    • 在单独的库模块(例如global.xq)中定义全局变量(例如$ global:test)
    • 在任何需要的地方导入该模块以提供对其变量的访问

  • 有没有办法在导入的库模块(例如test2.xq)中访问主XQuery模块中声明的变量(例如$ 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模块中定义和使用全局变量的正确方法是什么。

亲切的问候,

罗恩

2 个答案:

答案 0 :(得分:3)

显然,eXists从XSLT中采用了您可能熟悉的方法。在那里,您还可以通过导入/包含'祖先'模块(在include / import链中更高)引用当前模块外部声明的变量和参数。

据我所知,这不符合XQuery标准!

能够使用它显然非常实用,但有几个很好的理由不这样做。理想情况下,模块是独立的,可重复使用的组件,当它们依赖于这样的外部参数/变量时就不再是这种情况。最好将上下文信息作为参数传递给这些函数。并不总是看起来很优雅,但最终设计得更好。

某些实现提供了使用重定义变量值的替代选项。 MarkLogic有xdmp:set命令,我相信saxon也有变量赋值(或者是XSLT中的那个?)。您可以使用它来“初始化”模块。请注意,虽然模块不是对象,但请尽量避免使用这种方法来保存有状态信息。这也意味着您将依赖于特定于实现的功能。除非您能够使用更新工具。不确定是否打算以这种方式工作..

答案 1 :(得分:1)

在您的实际使用案例中 这些“变量”是什么?顾名思义,它们是否需要能够变化? (如果是这样,将它们放在文档中可能是正确的事情)。如果它们只是常量,那么你给出的方法 - 将它们放在一个模块/命名空间中并根据需要导入它 - 可能是正确的事情。

坦率地说,编写模块以假设其他地方定义的内容,但没有定义其他地方应该存在的内容,让我感到容易发生危险 - 如果没有其他原因,通过使读者更难以遵循流程控制。因此,我有点不清楚为什么这种行为是可取的。

考虑将您的配置封装在文档中,并将该文档作为参数传递给函数调用。