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

Posted

技术标签:

【中文标题】加载 XSLT 文件时解析相对路径【英文标题】:Resolving relative paths when loading XSLT files 【发布时间】:2011-04-11 14:54:54 【问题描述】:

我需要使用 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 文件并使用<xsl:import /> 标签将它们连接起来。使用此配置,我会收到 NullPointerException,因为它无法理解 XSLT 中存储的所有信息,因为它分布在不同的文件中。

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

更新

我已根据 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 文件的相对路径。

我做错了什么?

【问题讨论】:

【参考方案1】:

我使用的是 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;
    

【讨论】:

【参考方案2】:

我刚刚得到它,一个迟到的答案(在 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"/>

【讨论】:

非常感谢,这为我节省了几个小时。【参考方案3】:

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

【讨论】:

感谢您的回答,但它似乎并没有解决我的问题,尽管您的回答是有道理的。我已经用我对代码的更改更新了我的问题。 您可能需要获取 SystemID 的绝对路径。除非您知道它将在哪里解析“来自”的相对路径。尝试将该相对路径转换为绝对路径,例如:String xsltSystemId = new File(systemID).toURL().toExternalForm( );String xsltSystemId = new File(relativePath).getAbsolutePath(); 谢谢,我已经这样做了,并且我检查了当我执行 url.toExternalForm() 时它会获得一个绝对路径。但我现在不知道问题出在哪里。 这个解决方案非常适合我:xsltStreamSource.setSystemId(xsltFile.toURI().toString()); @james.garriss 经过几个小时的爬网和阅读浪费的 cmets 并没有简单地回答如何导入相关文件,突然间,你这个“单行”解决了我的相关“导入”问题。如果可以的话,我会给你 10000 票! :D

以上是关于加载 XSLT 文件时解析相对路径的主要内容,如果未能解决你的问题,请参考以下文章

如何使用相对路径在 XSLT 中引用 CSS

.net/xslt: <xsl:include> 与相对路径导致错误

module解析过程

在 Qt Creator 中加载具有相对路径的文件

Java Web中相对路径与绝对路径的分析

从相对路径和/或文件名解析绝对路径