加载XSLT文件时解析相对路径

我需要使用Apache FOP进行XSL转换,我有这样的代码:

//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文件,并用标签加入它们。 使用此配置,我得到一个NullPointerException,因为它不了解存储在XSLT中的所有信息,因为它分布在不同的文件上。

我想知道是否有任何方法可以在Source xsltSrc变量中加载所有这些文件,以便所有XSL信息都可用。

UPDATE

我根据Mads Hansen给出的答案更改了代码,但它仍然无效。 我必须在类路径中包含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文件的相对路径。

我究竟做错了什么?

我刚刚得到它,一个迟到的答案(在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’应该在类路径中):

  

当您将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); 

我正在使用Saxon 9.x,当我在样式表中使用文档时仍然存在问题。 样式表已正确解析,但是即使使用setSystemId,与jar文件中的样式表捆绑在一起的xmls也未按预期加载。 它导致文件未找到exception。 我更容易使用以下代码自定义解析器代码:

 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; } }