1

我在使用 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。

4

1 回答 1

1

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

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

如果您不知道要设置的合适的基本 URI,另一种方法是编写一个 ModuleURIResolver,例如,它可以通过对 getResourceAsStream() 进行另一个调用来获取模块。

于 2012-12-05T17:29:02.120 回答