2010-09-13 84 views
11

我需要做的使用Apache FOP XSL轉換的時候,我有這樣的代碼解決相對路徑:加載XSLT文件

//Setup FOP 
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out); 
//Setup Transformer 
Source xsltSrc = new StreamSource(new File(xslPath)); 
Transformer transformer = tFactory.newTransformer(xsltSrc); 

//Make sure the XSL transformation's result is piped through to FOP 
Result res = new SAXResult(fop.getDefaultHandler()); 
//Setup input 
Source src = new StreamSource(new File(xmlPath)); 
//Start the transformation and rendering process 
transformer.transform(src, res); 

其中xslPath是我的XSLT文件的存儲路徑。

我已經確認它在我只有一個XSLT文件時起作用,但在我的項目中,我已將事物分成幾個XSLT文件並將它們與<xsl:import />標記結合在一起。使用此配置,我得到一個NullPointerException,因爲它不能理解存儲在XSLT中的所有信息,因爲它分佈在不同的文件上。

我想知道是否有任何方法可以加載Source xsltSrc變量中的所有這些文件,以便提供所有XSL信息。

UPDATE

我已經改變了基於由馬德斯·漢森給出的答案代碼,但它仍然無法正常工作。我必須在類路徑中包含XSLT slt文件,因此我使用ClassLoader加載XSLT文件。我在執行url.toExternalForm()時檢查了URL是否有正確的路徑。這是我的新的一段代碼:

ClassLoader cl = this.getClass().getClassLoader(); 
String systemID = "resources/xslt/myfile.xslt"; 
InputStream in = cl.getResourceAsStream(systemID); 
URL url = cl.getResource(systemID); 
Source source = new StreamSource(in); 
source.setSystemId(url.toExternalForm()); 
transformer = tFactory.newTransformer(source); 

它發現並加載myfile.xslt但它仍然不能解決其他XSLT文件中的相對路徑。

我在做什麼錯?

回答

10

當你加載XSLT作爲StreamSource的並沒有設置SYSTEMID,處理器不知道「其中的」 XSLT是,不能解析相對路徑。

http://www.onjava.com/pub/a/onjava/excerpt/java_xslt_ch5/index.html?page=5

通過提供一個系統標識符作爲參數 到StreamSource的,你是 告訴XSLT處理器在哪裏 找commonFooter.xslt。如果沒有 此參數,那麼當處理器不能 解析此URI時,可能會遇到 錯誤。簡單的解決方法是 調用setSystemId()方法 如下:

// construct a Source that reads from an InputStream 
Source mySrc = new StreamSource(anInputStream); 
// specify a system ID (a String) so the 
// Source can resolve relative URLs 
// that are encountered in XSLT stylesheets 
mySrc.setSystemId(aSystemId); 
+0

感謝您的回答,但它似乎無法解決我的問題,儘管您的答案很有意義。我用代碼中的更改更新了我的問題。 – Javi 2010-09-15 10:06:08

+0

您可能需要獲取SystemID的絕對路徑。除非你知道它將在哪裏解決相對路徑「from」。嘗試將該相對路徑轉換爲類似以下內容的絕對路徑:'String xsltSystemId = new File(systemID).toURL()。toExternalForm();'或'String xsltSystemId = new File(relativePath).getAbsolutePath();' – 2010-09-15 11:04:21

+0

thanks ,我已經在那裏,我已經檢查,當我做url.toExternalForm()它獲得一個絕對路徑。但我不知道現在的問題在哪裏。 – Javi 2010-09-15 11:40:50

17

我剛得到它,一個遲到的回答(FOP上測試1.0)------

所有你需要的是設置一個URI解析器爲您的工廠,如下面的工作對我來說:

TransformerFactory transFact = TransformerFactory.newInstance(); 
StreamSource xsltSource = new StreamSource(xsl); 

// XXX for 'xsl:import' to load other xsls from class path 
transFact.setURIResolver(new ClasspathResourceURIResolver()); 
Templates cachedXSLT = transFact.newTemplates(xsltSource); 
Transformer transformer = cachedXSLT.newTransformer(); 


class ClasspathResourceURIResolver implements URIResolver { 
    @Override 
    public Source resolve(String href, String base) throws TransformerException { 
    return new StreamSource(XXX.getClassLoader().getResourceAsStream(href)); 
    } 
} 

和我的導入XSL(所以「imported.xsl」應該是在classpath中):

<xsl:import href="META-INF/companybusinesscredit/imported.xsl"/> 
+0

非常感謝,這節省了我數小時。 – 2015-09-24 19:44:27

2

我使用的是Saxon 9.x,並且在樣式表中使用文檔時仍然存在問題。樣式表已正確解析,但與jar文件中的樣式表一起捆綁的xml與setSystemId一樣無法按預期加載。它導致文件未找到異常。使用下面的代碼對代碼解析器進行自定義代碼更容易:

JarfileResolver jarfileResolver = new JarfileResolver(); 
transformer.setURIResolver(jarfileResolver); 


public class JarfileResolver implements URIResolver 
{ 
    public Source resolve(String fileName, String base) throws TransformerException 
    { 
     URL url = getClass().getClassLoader().getResource(fileName); 
     StreamSource jarFileSS = new StreamSource(); 

     try 
     { 
      InputStream jarfileIS = url.openStream(); 
      jarFileSS.setInputStream(jarfileIS); 
     } 
     catch(IOException ioExp) 
     { 
      throw new TransformerException(ioExp); 
     } 
     return jarFileSS; 
    } 
}