XQuery: совместное использование глобальных переменных между (импортированными) модулями - PullRequest
2 голосов
/ 06 марта 2012

К моему удивлению, я борюсь с довольно простым вопросом 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: пространство имен модуля test2 = "test2";

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

Это работает, но оставляет мне несколько вопросов:

  • Это способ сделать это:

    • определить глобальные переменные (например, $ global: test) в отдельном модуле библиотеки (например, global.xq)
    • импортировать этот модуль туда, где он необходим для обеспечения доступа к его переменным

    ?

  • Есть ли способ доступа к переменным, объявленным в основном модуле XQuery (например, $ test) в импортированных библиотечных модулях (например, test2.xq)?

Может кто-нибудь пролить свет на это? Я предполагаю, что главная причина, почему я сталкиваюсь с этой концепцией, заключается в том, что я привык к поведению eXist , которое, вероятно, слабее, чем следовало бы. В eXist модуль test2.xq может просто ссылаться на переменную $ global: test без импорта модуля global.xq:

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

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

Поскольку это работает в eXist, но не в Saxon, я начал задаваться вопросом, как правильно определить и использовать глобальные переменные в (импортированных) модулях XQuery.

С уважением,

Рон

Ответы [ 2 ]

3 голосов
/ 06 марта 2012

Очевидно, что eXists использует подход, который может быть вам знаком по XSLT. Здесь вы также можете ссылаться на переменные и параметры, объявленные вне текущего модуля через импорт / включение модулей 'предка' (выше в цепочке включения / импорта).

Насколько мне известно, это не соответствует стандарту XQuery!

Очевидно, что это очень удобно, но есть несколько веских причин, почемуне делать этого.В идеале модули являются автономными, повторно используемыми компонентами, и это больше не тот случай, когда они полагаются на такие внешние параметры / переменные.Было бы лучше передать контекстную информацию в качестве параметра для таких функций.Не всегда выглядит элегантно, но, в конце концов, это лучший дизайн.

Некоторые реализации предоставляют альтернативную опцию, использующую переопределение значений переменных.У MarkLogic есть команда xdmp: set, и я полагаю, что у saxon также есть присвоение переменных (или это было в XSLT?).Вы можете использовать это для «инициализации» модулей.Имейте в виду, что модули не являются объектами, поэтому старайтесь избегать использования такого подхода для хранения информации о состоянии.Это также означает, что вы будете полагаться на функции, специфичные для реализации.Если вы не сможете использовать средство обновления для этого.Не уверен, что это должно работать именно так ...

1 голос
/ 06 марта 2012

Что являются этими "переменными" в вашем реальном случае использования?Должны ли они, как следует из названия, иметь возможность варьироваться?(Если так, размещение их в документе может быть правильным).Если они просто константы, то подход, который вы дали - поместить их в один модуль / пространство имен и импортировать их по мере необходимости, - вероятно, правильная вещь.

Откровенно говоря, написание ваших модулей для предположения чего-то определенного в другом месте, но не определяя, где это должно быть в другом месте, мне кажется опасным, если не по какой-либо другой причине, из-за того, что читателю будет труднее следить за потоком контроля.Поэтому мне немного неясно, почему такое поведение было бы желательным.

Рассмотрите возможность инкапсуляции вашей конфигурации в документ и передачи этого документа в качестве аргумента для вызовов вашей функции.

...