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

如何在XSLT的xsl:import中使用类路径URI导入样式文件?

为Xalan指定类路径下的XSL导入路径

问题场景

在Gradle项目sample_gradle_project中使用Xalan(XSLT 1.0处理器)时,通过项目根路径src/main/resources/Afolder/step.xsl导入XSL文件在本地正常运行,但开发环境抛出IO异常,需要改用类路径方式指定<xsl:import>的href。

项目结构

sample_gradle_project
-src/main
-- java
-----service
--------- class.java
-- resources
----- Afolder
---------- step.xsl

现有问题代码

Java代码:

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.io.IOUtils;
import java.io.InputStream;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;

String unescaped_xsl = StringEscapeUtils.unescapeXml("&lt;xsl:import href = &quot;src/main/resources/Afolder/step.xsl&quot;/&gt;");

InputStream inputStream = IOUtils.toInputStream(unescaped_xsl);
Transformer transformer = transformerFactory.newTransformer(new StreamSource(inputStream));

报错信息:

Had IO Exception with stylesheet file: src/main/resources/Afolder/step.xsl

解决方案

1. 修正<xsl:import>的href路径

resources目录下的文件编译打包后会被放到类路径根目录,因此不需要src/main/resources前缀,直接使用类路径相对路径:

<xsl:import href="Afolder/step.xsl"/>

2. 为StreamSource设置类路径上下文URL

动态生成的样式表字符串没有默认的资源上下文,Xalan无法解析相对路径。需要通过类加载器获取资源URL,作为StreamSource的systemId,提供解析基准:

修改后的Java代码:

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.io.IOUtils;
import java.io.InputStream;
import java.net.URL;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;

// 更新导入路径为类路径相对路径
String unescaped_xsl = StringEscapeUtils.unescapeXml("&lt;xsl:import href = &quot;Afolder/step.xsl&quot;/&gt;");
InputStream inputStream = IOUtils.toInputStream(unescaped_xsl);

// 获取目标XSL的类路径URL,提取目录作为上下文
URL xslUrl = YourClass.class.getClassLoader().getResource("Afolder/step.xsl");
if (xslUrl == null) {
    throw new RuntimeException("类路径中未找到Afolder/step.xsl");
}
String systemId = xslUrl.toString().replace("step.xsl", "");

// 为StreamSource设置系统ID,提供路径解析上下文
StreamSource source = new StreamSource(inputStream);
source.setSystemId(systemId);

Transformer transformer = transformerFactory.newTransformer(source);

3. 推荐方案:直接加载类路径下的主样式表

如果主样式表也放在resources目录中,建议直接通过类加载器加载,而非动态生成字符串,Xalan会自动基于类路径解析导入:

假设主样式表main.xsl放在resources/styles/下,内容:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:import href="../Afolder/step.xsl"/>
    <!-- 自定义模板逻辑 -->
</xsl:stylesheet>

对应的Java代码:

import java.io.InputStream;
import java.net.URL;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;

// 从类路径加载主样式表
InputStream mainXslStream = YourClass.class.getClassLoader().getResourceAsStream("styles/main.xsl");
URL mainXslUrl = YourClass.class.getClassLoader().getResource("styles/main.xsl");

if (mainXslStream == null || mainXslUrl == null) {
    throw new RuntimeException("类路径中未找到styles/main.xsl");
}

StreamSource source = new StreamSource(mainXslStream);
source.setSystemId(mainXslUrl.toString());

Transformer transformer = transformerFactory.newTransformer(source);

核心说明

  • resources目录下的资源编译后位于类路径根,引用时无需src/main/resources前缀。
  • Xalan解析相对路径依赖StreamSource的systemId作为基准,必须设置为类路径资源的URL才能正确定位导入文件。
  • 动态生成样式表字符串易引发路径解析问题,优先直接加载类路径下的XSL文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 16:50:23