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

Saxonの質問は、 http://saxonica.plan.ioのSaxonフォーラムで最もよく尋ねられます。ここで尋ねられた質問は、おそらく最終的には気付かれることでしょうが、今回のように、私たちの最優先事項ではない場合もあります。

基本的な答えは、相対URIを解決するには、ベースURIがわかっている必要があるということです。つまり、XQueryCompilerのbaseURIプロパティが設定されていることを確認する必要があります。これは、ファイルからクエリをコンパイルした場合は自動的に発生しますが、InputStreamからコンパイルした場合は発生しません。

設定する適切なベースURIがわからない場合は、ModuleURIResolverを作成することもできます。これにより、たとえばgetResourceAsStream()で別の呼び出しを行ってモジュールをフェッチできます。

于 2012-12-05T17:29:02.120 に答える