You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java资源目录中XSLT文件引用路径错误,如何正确配置?

问题

我在Java资源目录中存放了example.xsl文件,通过class.getClassLoader().getResourceAsStream("example.xsl")获取该文件的输入流。但example.xsl内部包含引用语句<xsl:include href="dir/i18n.inc.xslt"/>,存放i18n.inc.xslt的dir目录也在资源目录中,部署后程序却在glassfish/domains/domain1/config目录下查找该文件。

使用环境:Java 17、Payara 6,通过Apache FOP实现XML转PDF,相关代码如下:

InputStream styleSheetInput = MyClass.class.getClassLoader().getResourceAsStream("example.xsl");

final FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

try {
    Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, outputStream);
    // Setup XSLT
    TransformerFactory factory = TransformerFactory.newInstance();
    Transformer transformer = factory.newTransformer(new StreamSource(styleSheetInput));

    // Set the value of a <param> in the stylesheet
    transformer.setParameter("versionParam", "2.0");

    // Setup input for XSLT transformation
    Source src = new StreamSource(datafile);

    // Resulting SAX events (the generated FO) must be piped through to FOP
    Result res = new SAXResult(fop.getDefaultHandler());

    // Start XSLT transformation and FOP processing
    transformer.transform(src, res);
}

报错信息:

[tid: _ThreadID=279 _ThreadName=__ejb-thread-pool11] [timeMillis: 1693598088423] [levelVal
/usr/local/payara6/glassfish/domains/domain1/config/dir/i18n.inc.xslt (No such file or directory)]]

希望将XSLT文件放在资源目录中而非config目录,如何修改让程序在资源目录中查找该文件?

解决方案

问题根源在于:仅用InputStream创建StreamSource时,Transformer没有获取到XSL文件的基础URI,解析相对路径时会默认使用当前工作目录(Payara的config目录)。解决核心是给StreamSource设置正确的系统ID,让Transformer基于资源的实际位置解析相对引用。

方法一:通过资源URL设置系统ID

先获取example.xsl的资源URL,再基于此URL设置StreamSource的系统ID,代码修改如下:

// 获取资源URL,而非直接拿InputStream
URL styleSheetUrl = MyClass.class.getClassLoader().getResource("example.xsl");
InputStream styleSheetInput = styleSheetUrl.openStream();

// 创建StreamSource并设置系统ID(资源的完整URI)
StreamSource styleSheetSource = new StreamSource(styleSheetInput);
styleSheetSource.setSystemId(styleSheetUrl.toString());

// 后续用styleSheetSource创建Transformer
Transformer transformer = factory.newTransformer(styleSheetSource);

方法二:直接使用资源URL创建StreamSource

可以省略InputStream,直接用资源URL的字符串形式创建StreamSource,Transformer会自动识别基础URI:

URL styleSheetUrl = MyClass.class.getClassLoader().getResource("example.xsl");
StreamSource styleSheetSource = new StreamSource(styleSheetUrl.toExternalForm());

Transformer transformer = factory.newTransformer(styleSheetSource);

说明

设置系统ID后,XSL中的<xsl:include href="dir/i18n.inc.xslt"/>会基于example.xsl的资源位置(即资源目录)解析相对路径,从而正确找到dir/i18n.inc.xslt文件,无需修改XSL中的href路径。

内容的提问来源于stack exchange,提问作者liubitel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:40:13