如何使用Saxon导入xquery模块

时间:2012-11-30 17:22:29

标签: xquery saxon

我遇到了一些使用Saxon9HE运行Xquery的麻烦,它有一个外部模块的引用。 我希望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。

1 个答案:

答案 0 :(得分:1)

撒克逊问题最好在撒克逊论坛上http://saxonica.plan.io提出 - 这里提出的问题最终可能会被注意到,但有时候,这次,他们不是我们的首要任务。

基本答案是,对于要解析的相对URI,需要知道基URI,这意味着您需要确保设置XQueryCompiler中的baseURI属性。如果从File编译查询,则会自动执行此操作,但如果从InputStream编译查询则不会。

如果您不知道要设置的合适基URI​​,可以选择编写ModuleURIResolver,例如可以通过在getResourceAsStream()上再次调用来获取模块。