如何配置Apache Xalan-Transformer避免生成空行?
解决Xalan XML转换器重复格式化时生成大量空行的问题
问题现象
使用Xalan转换器对XML进行缩进格式化时,首次处理无缩进的XML(如:
<foo><bar/></foo>
)会得到符合预期的格式化结果:
<?xml version="1.0" encoding="UTF-8"?><foo> <bar/> </foo>
但再次对该格式化后的XML进行转换时,会生成大量空行:
<?xml version="1.0" encoding="UTF-8"?><foo> <bar/> </foo>
且每次重复转换,空行数量都会持续增加。而Saxon转换器不存在此问题。
问题原因
Xalan默认的XML格式化逻辑不会移除输入XML中的空白文本节点,每次转换都会在原有空白的基础上叠加新的缩进空白,导致空行累积。
解决方法
通过自定义XSLT样式表,先剥离XML中不必要的空白节点,再执行缩进格式化,确保重复处理时结果一致。
步骤1:定义XSLT样式表
创建一个用于清理空白并格式化XML的XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 剥离所有元素的空白文本节点 --> <xsl:strip-space elements="*"/> <!-- 开启XML缩进输出 --> <xsl:output method="xml" indent="yes"/> <!-- 复制所有节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
步骤2:修改测试代码
使用上述XSLT创建Transformer,替换默认的Transformer实例:
import java.io.StringReader; import java.io.StringWriter; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.junit.Assert; import org.junit.jupiter.api.Test; class TransformerTest { @Test void formattingShouldBeIdempotent() throws Exception { // 定义XSLT样式表字符串 String xslt = """ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:strip-space elements="*"/> <xsl:output method="xml" indent="yes"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> """; TransformerFactory factory = TransformerFactory.newDefaultInstance(); // 使用XSLT创建Transformer Transformer transformer = factory.newTransformer(new StreamSource(new StringReader(xslt))); String transformed1 = transform("<foo><bar/></foo>", transformer); String transformed2 = transform(transformed1, transformer); Assert.assertEquals(transformed1, transformed2); } private String transform(String input, Transformer transformer) throws TransformerException { Source source = new StreamSource(new StringReader(input)); StringWriter outWriter = new StringWriter(); StreamResult result = new StreamResult(outWriter); transformer.transform(source, result); return outWriter.getBuffer().toString(); } }
原理说明
<xsl:strip-space elements="*"/>会移除所有元素中的空白文本节点,避免原有空白影响后续格式化。<xsl:output method="xml" indent="yes"/>开启缩进输出,确保生成格式规范的XML。- 模板匹配逻辑会完整复制原XML的所有节点和属性,仅处理空白和格式化,不改变XML的业务内容。
内容的提问来源于stack exchange,提问作者klimpergeist
相关产品推荐
相关产品推荐

