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

使用Saxon XSLT引擎处理XML时如何让XSL文件定位所需XSD文件

问题描述

项目目录结构

src/main
├── assembly
│   └── package.xml
├── java
│   └── org
│       └── legible
│           ├── kafka
│           │   ├── CamelSftpSourceConnector.java
│           │   ├── CamelSftpSourceConnectorConfig.java
│           │   ├── CamelSftpSourceTask.java
│           │   ├── CamelSourceTask.java
│           │   └── package-info.java
│           └── reference_tag_converter
│               └── ReferenceTagTransformer.java
└── resources
    ├── schemas
    │   ├── ONIX_BookProduct_3.0_reference.xsd
    │   ├── ONIX_BookProduct_3.0_short.xsd
    │   ├── ONIX_BookProduct_CodeLists.xsd
    │   └── ONIX_XHTML_Subset.xsd
    ├── switch-onix-3.0-tagnames-2.0_v1.3.xsl
    └── switch-onixmessage-tag.xsl   

问题代码

ReferenceTagTransformer类中实例化XSLT转换器的代码如下:

StreamSource switchOnixMessageTagStylesheet = new StreamSource(this.getClass().getClassLoader().getResourceAsStream("switch-onixmessage-tag.xsl"));
StreamSource transformReferenceTagStylesheet = new StreamSource(this.getClass().getClassLoader().getResourceAsStream("switch-onix-3.0-tagnames-2.0_v1.3.xsl"));

Processor processor = new Processor(false);

XsltCompiler compiler = processor.newXsltCompiler();

XsltExecutable switchOnixMessageStylesheet = compiler.compile(switchOnixMessageTagStylesheet);
XsltTransformer onixMessageTagTransformer = switchOnixMessageStylesheet.load();

XsltExecutable convertTagsStylesheet = compiler.compile(transformReferenceTagStylesheet);
XsltTransformer referenceTagTransformer = convertTagsStylesheet.load();

referenceTagTransformer.setParameter(new QName("result-document"), new XdmAtomicValue(Paths.get("", "temp.xml").toString()));

// path to XSD schemas
referenceTagTransformer.setParameter(new QName("input-path"), new XdmAtomicValue("schemas"));

问题现象

调用转换器的transform方法时,样式表抛出错误,无法解析赋值给input-path变量的schemas路径。


解决方案

问题原因

你当前传入的schemas是相对路径,XSLT执行时的默认工作目录不是项目的resources目录,所以无法直接定位到schema文件。如果项目是打包成jar包运行,jar包内部的资源也无法通过普通文件路径直接访问。

分场景处理方案

场景1:打包后resources目录会被解压到文件系统

直接读取schemas目录的绝对路径传入即可,代码修改如下:

// 获取schemas目录的绝对路径
URL schemasUrl = this.getClass().getClassLoader().getResource("schemas");
String schemasAbsolutePath = Paths.get(schemasUrl.toURI()).toString();
referenceTagTransformer.setParameter(new QName("input-path"), new XdmAtomicValue(schemasAbsolutePath));

场景2:项目打包为jar包运行,resources目录未解压

XSLT的document()方法无法直接读取jar包内部的资源,你需要先将schemas目录复制到系统临时目录,再传入临时目录的路径:

import java.nio.file.StandardCopyOption;

// 创建临时目录存放schema文件
Path tempSchemasDir = Files.createTempDirectory("onix_schemas_");

// 逐个将resources下的schema文件复制到临时目录
List<String> schemaFiles = Arrays.asList(
    "ONIX_BookProduct_3.0_reference.xsd",
    "ONIX_BookProduct_3.0_short.xsd",
    "ONIX_BookProduct_CodeLists.xsd",
    "ONIX_XHTML_Subset.xsd"
);
for (String fileName : schemaFiles) {
    try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("schemas/" + fileName)) {
        Files.copy(is, tempSchemasDir.resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
    }
}

// 传入临时目录路径
referenceTagTransformer.setParameter(new QName("input-path"), new XdmAtomicValue(tempSchemasDir.toString()));

// 转换完成后记得删除临时目录释放空间

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 01:06:04