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

如何在XSL与Saxon-HE中正确禁用输出转义?

问题描述

我正在使用Saxon-HE处理以下XSLT代码:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:key name="elelsById" match="elel" use="@elelEntity" />

    <xsl:template match="/">
        <xsl:text disable-output-escaping="yes">&#xA;&lt;!DOCTYPE dmodule [&#xA;</xsl:text>
        <xsl:text disable-output-escaping="yes">&lt;!NOTATION cgm PUBLIC "-//USA-DOD//NOTATION Computer Graphics Metafile//EN"&gt;&#xA;</xsl:text>

        <xsl:for-each select="//elel[generate-id() = generate-id(key('elelsById', @elelEntity)[1])]">
            <xsl:text disable-output-escaping="yes">&lt;!ENTITY </xsl:text>
            <xsl:value-of select="@elelEntity" />
            <xsl:text> SYSTEM "</xsl:text>
            <xsl:value-of select="@elelEntity" />
            <xsl:text disable-output-escaping="yes">.cgm" NDATA cgm &gt;&#xA;</xsl:text>
        </xsl:for-each>

        <xsl:text disable-output-escaping="yes">]&gt;&#xA;</xsl:text>
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

当前输出结果:

<?xml version="1.0" encoding="UTF-8"?>
&lt;!DOCTYPE dmodule [
&lt;!NOTATION cgm PUBLIC "-//USA-DOD//NOTATION Computer Graphics Metafile//EN"&gt;
&lt;!ENTITY ELEL-A-01 SYSTEM "ELEL-A-01.cgm" NDATA cgm &gt;
&lt;!ENTITY ELEL-A-05 SYSTEM "ELEL-A-05.cgm" NDATA cgm &gt;
]&gt;
<!-- xml content -->

我预期输出中的&lt;和&gt;会被替换为<和>,但实际未生效。即使移除disable-output-escaping="yes",结果依然相同。我了解到saxon:doctype扩展仅适用于Saxon-PE或Saxon-EE版本,请问我的实现中遗漏了什么?

解决方案

核心问题原因

Saxon-HE对disable-output-escaping(以下简称DOE)的支持有限,且DOE的生效依赖输出方式:

  • DOE仅在序列化到字符流时生效:如果输出目标是DOM树或其他非字符流格式,DOE会被直接忽略。
  • XSLT 2.0规范中DOE是可选特性:Saxon-HE作为免费版本,对该特性的支持并不完整,尤其是处理DOCTYPE这类不属于XML实例内容的部分时。

可行替代方案

方案1:切换为纯文本输出模式

放弃XSLT的XML序列化机制,将整个输出作为纯文本处理,直接写入目标字符流:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:key name="elelsById" match="elel" use="@elelEntity" />

    <xsl:template match="/">
        <!-- 输出XML声明 -->
        <xsl:text><?xml version="1.0" encoding="UTF-8"?>&#xA;</xsl:text>
        <!-- 输出DOCTYPE头部 -->
        <xsl:text><!DOCTYPE dmodule [&#xA;</xsl:text>
        <xsl:text><!NOTATION cgm PUBLIC "-//USA-DOD//NOTATION Computer Graphics Metafile//EN">&#xA;</xsl:text>
        <!-- 遍历生成实体声明 -->
        <xsl:for-each select="//elel[generate-id() = generate-id(key('elelsById', @elelEntity)[1])]">
            <xsl:text><!ENTITY </xsl:text>
            <xsl:value-of select="@elelEntity" />
            <xsl:text> SYSTEM "</xsl:text>
            <xsl:value-of select="@elelEntity" />
            <xsl:text>.cgm" NDATA cgm >&#xA;</xsl:text>
        </xsl:for-each>
        <!-- 闭合DOCTYPE -->
        <xsl:text>]>&#xA;</xsl:text>
        <!-- 将XML内容转为文本输出 -->
        <xsl:value-of select="." disable-output-escaping="yes"/>
    </xsl:template>
</xsl:stylesheet>

注意:需确保输入XML格式良好,避免输出时出现格式错误。

方案2:指定序列化参数

调用Saxon-HE时,通过命令行参数强制使用文本序列化模式,确保DOE生效。示例命令:

java -jar saxon-he-xxx.jar -s:input.xml -xsl:stylesheet.xsl -o:output.xml -method:text

此方式需手动处理XML内容的转义逻辑,保证输出格式合规。

方案3:后处理替换符号

用脚本(如Python、Perl)对输出文件进行后处理,直接替换&lt;和&gt;为实际尖括号,这是最快捷的临时解决办法。

关键注意事项

  • Saxon-HE确实不支持saxon:doctype扩展,无需尝试依赖该特性。
  • DOE属于非常规用法,仅在必要场景下使用,优先考虑标准序列化机制。
  • 若长期处理此类需求,升级到Saxon-PE/EE会更高效,官方扩展对DOCTYPE的支持更完善。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 23:32:02