升级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规范中关于空白处理的定义,仅在样式表或输出配置明确指定的情况下才生成空白,目的是减少不必要的冗余空白,提升输出内容的紧凑性。
解决方案
有两种可行方式恢复旧版本的输出行为:
修改样式表,手动控制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声明及换行符( 代表换行) --> <xsl:text disable-output-escaping="yes"><?xml version="1.0" encoding="UTF-8"?> </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>通过代码设置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
相关产品推荐
相关产品推荐

