2012-03-06 92 views
2

令我惊讶的是,我正在与一个非常基本的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 .x: module namespace test2 =“test2”;

    import module namespace global="global" at "global.xq"; 
    
    declare function test2:echo() { 
        $global:test 
    }; 
    

这工作,但给我留下了一些问题:

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

    • 定义全局变量(如$全球:测试)在一个单独的库模块中(例如global.xq)
    • 将模块导入需要提供的任何模块访问其变量

  • 有没有办法访问导入的库模块(例如test2.xq)中的主XQuery模块(例如$ test)中声明的变量?

任何人都可以阐明这一点吗?我想我发现自己在这个概念上挣扎的主要原因是因为我习惯于eXist的行为,这可能比它应该放松。在存在,test2.xq模块可以直接参考$全局:测试变量,而不用导入global.xq模块:

module namespace test2="test2"; 
declare namespace global="global"; 

declare function test2:echo() { 
    $global:test 
}; 

由于这部作品中不存在,但不是在撒克逊人,我就开始琢磨什么在(导入的)XQuery模块中定义和使用全局变量的正确方法。

亲切的问候,

罗恩

回答

3

显然存在需要,可能是你熟悉的,从XSLT.In那里,你也可以指通过进口/包括宣布当前模块外部变量和参数的方法'祖先'模块(在包含/进口链中较高)。

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

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

一些实现提供了使用重定义变量值的备选选项。 MarkLogic有xdmp:set命令,我相信saxon也有变量赋值(或者是在XSLT中?)。你可以用它来'初始化'模块。尽管这些模块不是对象,所以尽量避免使用这种方法来保存有状态的信息。这也意味着你会依赖实现特定的功能。除非你能够使用更新工具。不知道这是打算这样的方式,虽然..

+0

谢谢你的想法。我非常清楚,我可能会遇到基于非标准行为的假设。然而,我在网上找不到关于这种设计模式的许多有用提示。我不喜欢针对这种基本需求的特定于供应商的扩展。你会推荐我的原始问题中的工作方法(即在专用库模块中定义全局变量并根据需要导入)作为使所有(导入)XQuery模块都可访问全局变量的标准方法吗?或者你看到其他(符合)的可能性? – rvdb 2012-03-06 15:01:07

+1

@rvdb我建议通过参数传递这样的值给每个调用。将大量的上下文信息收集到一个小的XML片段中非常容易,并且可以通过它。它是迄今为止最可扩展和最干净的。 像你这样导入一个共享的全局模块是最明智的选择,除非你有足够的理由想要初始化我描述的行为。 HTH! – grtjn 2012-03-06 16:21:50

1

什么这些“变量”在您的实际使用情况?顾名思义,他们是否需要能够改变? (如果是这样,将它们放在文档中可能是正确的事情)。如果它们只是常量,那么你给的方法 - 将它们放入单个模块/名称空间并根据需要导入 - 可能是正确的。坦白地说,编写你的模块来假设其他地方定义的东西,但没有定义其他地方应该在哪里,这使我容易冒险 - 如果没有其他原因,通过让读者更难以遵循控制流程。因此,我有点不清楚为什么这种行为是可取的。

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

+0

不,他们是常数;我正在考虑更多的配置文件,其中包含可由泛型代码使用的特定于应用程序的值。然后通用代码可以用于不同的应用程序,每个应用程序都有自己的配置值。 我想你的第二个评论涉及我提到的eXist行为?在这种情况下,我确实同意:我宁愿采取符合规格的路线。 – rvdb 2012-03-06 16:41:39

+0

@rvdb - 啊,gotcha。我个人提供配置值的方法是通过配置文件注入配置文件,并将其作为参数传递给需要此类值的任何调用。现在,我将这个文档作为上下文参数传递给实际的调用,而不是将其存储在数据库中,尽管这种特定的方法是我不确定我是长期销售的......但是方式,明确比隐含更好。 – 2012-03-06 17:45:36

+0

@rvdb ...实际上,它看起来像grtjn独立地提出了相同的方法;我正在阅读,作为我自己使用的维护/验证水平。 :) – 2012-03-06 17:47:41