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

Saxon升级至10.6后xsl:result-document报错求助

问题:Saxon从8.7升级到10.6后xsl:result-document报错

近期将Saxon版本从8.7升级至10.6,此前在8.7版本中xsl:result-document可正常工作,现遇到报错,文件生成部分内容后程序失败。

相关代码与信息

XML输入格式

<?xml version="1.0" encoding="UTF-8"?>
<Statements>
<title>This is an example document</title>
<Statement>
    <Invoice>1234567</Invoice>
    <Name>ABC</Name>
</Statement>
<Statement>
    <Invoice>9876543</Invoice>
    <Name>XYZ</Name>
</Statement>
</Statements>

XSLT片段

<xsl:template name="EnhanceAccount">
    <xsl:result-document href="/data/ebpp/{$FileName}_EnhancedAccountInfo.jr1" method="text">
        <xsl:text>InvoiceNumber</xsl:text>
        <xsl:text>&#10;</xsl:text>
        <xsl:for-each select="//Statement">
            <xsl:value-of select="InvoiceNumber"/>
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each>
    </xsl:result-document>
</xsl:template>

报错信息

net.sf.saxon.trans.XPathException: The system identifier of the principal output file is unknown
at net.sf.saxon.lib.StandardOutputResolver.resolve(StandardOutputResolver.java:89)
at net.sf.saxon.lib.OutputURIResolverWrapper.resolve(OutputURIResolverWrapper.java:58)
at net.sf.saxon.expr.instruct.ResultDocument.makeReceiver(ResultDocument.java:528)
at net.sf.saxon.expr.instruct.ResultDocument.processLeft(ResultDocument.java:477)

已生成的文件内容

InvoiceNumber
1234567

Java调用代码

File stylesheet = new File(enhanceAccountTemplate);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Templates cachedXSLT = transformerFactory.newTemplates(new StreamSource(stylesheet));
Transformer transformer = cachedXSLT.newTransformer();
transformer.setParameter("FileName", inpfile);
Source src = new StreamSource(inputStream);
Result res = new StreamResult(out);
transformer.transform(src, res);

问题原因及解决方案

核心原因

Saxon 9.0及以上版本对xsl:result-document的输出解析逻辑做了调整:当主输出结果(即transform方法传入的Result对象)未设置**系统标识符(System ID)**时,即使xsl:result-document使用绝对路径,Saxon的StandardOutputResolver依然会依赖主输出的系统ID完成路径解析,从而抛出该错误。而Saxon 8.7版本没有这个强制校验逻辑。

另外你的XSLT存在节点选择错误:XML中Statement下的节点是<Invoice>,但XSLT里用了select="InvoiceNumber",这会导致循环中大部分内容无法正确输出。

解决方案

  1. 为主输出Result设置系统标识符
    修改Java代码中StreamResult的初始化逻辑,添加合法的系统ID(可以是真实文件路径,也可以是虚拟URI):
File stylesheet = new File(enhanceAccountTemplate);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Templates cachedXSLT = transformerFactory.newTemplates(new StreamSource(stylesheet));
Transformer transformer = cachedXSLT.newTransformer();
transformer.setParameter("FileName", inpfile);
Source src = new StreamSource(inputStream);
Result res = new StreamResult(out);
// 添加系统ID,可使用虚拟URI或真实文件路径
res.setSystemId("file:/dummy/main-output");
transformer.transform(src, res);
  1. 修正XSLT中的节点选择错误
    将XSLT里的select="InvoiceNumber"改为select="Invoice",匹配XML中的实际节点:
<xsl:template name="EnhanceAccount">
    <xsl:result-document href="/data/ebpp/{$FileName}_EnhancedAccountInfo.jr1" method="text">
        <xsl:text>InvoiceNumber</xsl:text>
        <xsl:text>&#10;</xsl:text>
        <xsl:for-each select="//Statement">
            <xsl:value-of select="Invoice"/> <!-- 修正节点名称 -->
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each>
    </xsl:result-document>
</xsl:template>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 17:21:15