2012-11-30 42 views
1

我遇到一些麻煩,運行一個帶有Saxon9HE的Xquery,它有一個外部模塊的引用。 我想撒克遜解決與相對路徑相當絕對的模塊。如何導入一個使用Saxon的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; 
} 

}

模塊聲明

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

從主的XQuery

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

如果把它變成像一個相對路徑

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

我得到的線22列

錯誤1 XQST0059:java.io.FileNotFoundException

我不知道該ModuleURIResolver應該如何使用。

回答

1

撒克遜的問題最好問在撒克遜論壇http://saxonica.plan.io - 這裏提出的問題可能會最終被注意到,但有時候,像這個時候,他們不是我們的首要任務。

基本的答案是,要解析相對URI,需要知道基本URI,這意味着您需要確保設置了XQueryCompiler中的baseURI屬性。如果您從文件編譯查詢,則會自動發生,但如果您從InputStream進行編譯,則會發生這種情況。

如果您不知道要設置的合適的基本URI,那麼另一種方法是編寫一個ModuleURIResolver,例如可以通過在getResourceAsStream()上再次調用來獲取該模塊。

+0

嗨邁克爾,調用setModuleURIResolver沒有幫助。我相信解決方法甚至沒有觸發。 何時/何地應該實際進行呼叫? 只要沒有外部模塊進來,該代碼就可以工作,那仍然是用setModuleURIResolver調用Saxon轉換的正確方法嗎? 謝謝 – AleIla

+0

這裏的代碼已經更新 – AleIla

+0

你正在創建一個新的StaticQueryContext並設置模塊URI解析器,但是你沒有使用這個StaticQueryContext來編譯。在XQueryCompiler本身上使用setModuleURIResolver。 –

相關問題