Как импортировать модуль xquery с помощью Saxon

У меня возникли проблемы с запуском Xquery с Saxon9HE, в котором есть ссылка на внешний модуль. Я хотел бы, чтобы Saxon разрешил модуль с относительным путем, а не с абсолютным.

объявление модуля

module namespace common = "http://my-xquery-utils";

из основного xquery

import module namespace common = "http://my-xquery-utils" at "/home/myself/common.xquery";

из моего java-кода

public class SaxonInvocator {

private static Processor proc = null;
private static XQueryEvaluator xqe = null;
private static DocumentBuilder db = null;
private static StaticQueryContext ctx = null;

/**
 * Utility for debug, should not be called outside your IDE
 *
 * @param args xml, xqFile, xqParameter
 */
public static void main(String[] args) {
    XmlObject instance = null;
    try {
        instance = XmlObject.Factory.parse(new File(args[0]));
    } catch (XmlException ex) {
        Logger.getLogger(SaxonInvocator.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex){
        Logger.getLogger(SaxonInvocator.class.getName()).log(Level.SEVERE, null, ex);
    }
    System.out.print(transform(instance, args[1], args[2]));
}

public static String transform(XmlObject input, String xqFile, String xqParameter) {
    String result = null;
    try {
        proc = new Processor(false);
        proc.getUnderlyingConfiguration().getOptimizer().setOptimizationLevel(0);
        ctx = proc.getUnderlyingConfiguration().newStaticQueryContext();
        ctx.setModuleURIResolver(new ModuleURIResolver() {

            @Override
            public StreamSource[] resolve(String moduleURI, String baseURI, String[] locations) throws XPathException {
                StreamSource[] modules = new StreamSource[locations.length];
                for (int i = 0; i < locations.length; i++) {
                    modules[i] = new StreamSource(getResourceAsStream(locations[i]));
                }
                return modules;
            }
        });

        db = proc.newDocumentBuilder();
        XQueryCompiler comp = proc.newXQueryCompiler();
        XQueryExecutable exp = comp.compile(getResourceAsStream(xqFile));
        xqe = exp.load();
        ByteArrayInputStream bais = new ByteArrayInputStream(input.xmlText().getBytes("UTF-8"));
        StreamSource ss = new StreamSource(bais);
        XdmNode node = db.build(ss);
        xqe.setExternalVariable(
                new QName(xqParameter), node);
        result = xqe.evaluate().toString();
    } catch (SaxonApiException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return result;
}

public static InputStream getResourceAsStream(String resource) {
    InputStream stream = SaxonInvocator.class.getResourceAsStream("/" + resource);
    if (stream == null) {
        stream = SaxonInvocator.class.getResourceAsStream(resource);
    }
    if (stream == null) {
        stream = SaxonInvocator.class.getResourceAsStream("my/project/" + resource);
    }
    if (stream == null) {
        stream = SaxonInvocator.class.getResourceAsStream("/my/project/" + resource);
    }
    return stream;
}

}

Если изменить его на относительный путь, например

import module namespace common = "http://my-xquery-utils" at "common.xquery";

я получил

Ошибка в строке 22, столбце 1 XQST0059: java.io.FileNotFoundException

Я не уверен, как следует использовать ModuleURIResolver.


person AleIla    schedule 30.11.2012    source источник


Ответы (1)


Саксонские вопросы лучше всего задавать на саксонском форуме по адресу http://saxonica.plan.io. быть замеченными в конце концов, но иногда, как в этот раз, они не являются нашим главным приоритетом.

Основной ответ заключается в том, что для разрешения относительного URI необходимо знать базовый URI, а это значит, что необходимо убедиться, что свойство baseURI в XQueryCompiler установлено. Это происходит автоматически, если вы компилируете запрос из файла, но не если вы компилируете его из InputStream.

Если вы не знаете подходящий базовый URI для установки, альтернативой является написание ModuleURIResolver, который мог бы, например, получить модуль, выполнив еще один вызов getResourceAsStream().

person Michael Kay    schedule 05.12.2012
comment
Привет, Майкл, вызов setModuleURIRResolver не помог. Я считаю, что метод разрешения даже не запускается. Когда/где должен быть сделан звонок? Этот код работал до тех пор, пока не поступали внешние модули. Это все еще правильный способ вызвать преобразование Saxon с помощью setModuleURIResolver? Спасибо - person AleIla; 10.12.2012
comment
Вы создаете новый StaticQueryContext и устанавливаете для него преобразователь URI модуля, но не используете этот StaticQueryContext для компиляции. Используйте setModuleURIResolver для самого XQueryCompiler. - person Michael Kay; 11.12.2012