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

升级Xalan-J至2.7.3后XML声明后无换行,如何保留旧格式?

问题

将Xalan-J从2.7.0版本升级至2.7.3版本时,发现自2.7.1版本起,转换后的文档在XML声明后不再自动换行。由于默认设置omit-xml-declaration为no,XML声明会自动添加。

输入文档

<?xml version="1.0" encoding="UTF-8"?>
<input-root>
<input-a id="1">
<input-b id="1">ABC</input-b>
<input-b id="2">DEF</input-b>
<input-b id="3">GHI</input-b>
<input-b id="4">JKL</input-b>
</input-a>
<input-a id="2">
<input-b id="1">MNO</input-b>
<input-b id="2">PQR</input-b>
<input-b id="4">STU</input-b>
</input-a>
</input-root>

样式表

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/input-root">

        <output-root>
            <xsl:for-each select="input-a">
                <output-a>
                    <xsl:attribute name="id">
                        <xsl:value-of select="@id"/>
                    </xsl:attribute>
                    <xsl:for-each select="input-b">
                        <output-b>
                            <xsl:attribute name="id">
                                <xsl:value-of select="@id"/>
                            </xsl:attribute>
                            <xsl:value-of select="text()"/>
                        </output-b>
                    </xsl:for-each>
                </output-a>
            </xsl:for-each>
        </output-root>

    </xsl:template>

</xsl:stylesheet>

预期输出(Xalan-J 2.7.0及更早版本)

<?xml version="1.0" encoding="UTF-8"?>
<output-root>
<output-a id="1">
<output-b id="1">ABC</output-b>
<output-b id="2">DEF</output-b>
<output-b id="3">GHI</output-b>
<output-b id="4">JKL</output-b>
</output-a>
<output-a id="2">
<output-b id="1">MNO</output-b>
<output-b id="2">PQR</output-b>
<output-b id="4">STU</output-b>
</output-a>
</output-root>

实际输出(Xalan-J 2.7.1及之后版本)

<?xml version="1.0" encoding="UTF-8"?><output-root>
<output-a id="1">
<output-b id="1">ABC</output-b>
<output-b id="2">DEF</output-b>
<output-b id="3">GHI</output-b>
<output-b id="4">JKL</output-b>
</output-a>
<output-a id="2">
<output-b id="1">MNO</output-b>
<output-b id="2">PQR</output-b>
<output-b id="4">STU</output-b>
</output-a>
</output-root>

虽然该输出为有效XML,但生产系统生成的XML文档需保持原有格式以满足贸易伙伴要求,且因CVE-2022-34169漏洞必须升级版本。需明确:

  • 该变更的原因是什么?
  • 是否有方法在升级后保留旧版本的输出行为?

答案

变更原因

Xalan-J 2.7.1版本对XML输出的空白处理逻辑进行了优化调整。旧版本中XML声明后自动添加换行属于未严格遵循规范的“额外”空白输出;新版本则严格对齐XSLT规范中关于空白处理的定义,仅在样式表或输出配置明确指定的情况下才生成空白,目的是减少不必要的冗余空白,提升输出内容的紧凑性。

解决方案

有两种可行方式恢复旧版本的输出行为:

  1. 修改样式表,手动控制XML声明与换行
    关闭默认XML声明生成,手动输出带换行的声明内容:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <!-- 关闭默认XML声明,改为手动输出 -->
        <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    
        <xsl:template match="/">
            <!-- 输出XML声明及换行符(&#10;代表换行) -->
            <xsl:text disable-output-escaping="yes">&lt;?xml version="1.0" encoding="UTF-8"?&gt;&#10;</xsl:text>
            <xsl:apply-templates select="input-root"/>
        </xsl:template>
    
        <xsl:template match="/input-root">
            <output-root>
                <xsl:for-each select="input-a">
                    <output-a>
                        <xsl:attribute name="id">
                            <xsl:value-of select="@id"/>
                        </xsl:attribute>
                        <xsl:for-each select="input-b">
                            <output-b>
                                <xsl:attribute name="id">
                                    <xsl:value-of select="@id"/>
                                </xsl:attribute>
                                <xsl:value-of select="text()"/>
                            </output-b>
                        </xsl:for-each>
                    </output-a>
                </xsl:for-each>
            </output-root>
        </xsl:template>
    </xsl:stylesheet>
    
  2. 通过代码设置Xalan扩展属性
    利用Xalan-J的扩展输出属性控制换行行为,在Java代码中配置Transformer时添加:

    Transformer transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(xslFile));
    // 保留原有缩进设置
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    // 指定行分隔符为换行
    transformer.setOutputProperty("{http://xml.apache.org/xalan}line-separator", "\n");
    

    确保使用的TransformerFactory是Xalan的实现类,以支持该扩展属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 11:34:55