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

2022-09-02 20:10:48

我需要使用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);

where 是存储 XSLT 文件的路径。xslPath

我已经确认当我只有一个XSLT文件时它可以工作,但是在我的项目中,我已经将内容分成几个XSLT文件,并用标记连接它们。使用此配置,我得到一个 NullPointerException,因为它不理解存储在 XSLT 中的所有信息,因为它分布在不同的文件上。<xsl:import />

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

更新

我已经根据Mads Hansen给出的答案更改了代码,但它仍然不起作用。我必须在类路径中包含 XSLT slt 文件,因此我使用 ClassLoader 加载 XSLT 文件。我已经检查了执行时URL是否具有正确的路径。这是我的新代码:url.toExternalForm()

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

它会查找并加载,但仍然无法解析其他 XSLT 文件的相对路径。myfile.xslt

我做错了什么?


答案 1

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

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

答案 2

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

推荐