2010-09-13 88 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; 
    } 
}