如何修改XSLT以去除XML多余空格并保留空行?
问题描述
需要处理Maven项目的pom.xml文件,要求去除元素内的多余空格,但保留原文件中的空行。
原始XML内容
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example.application</groupId> <artifactId>sample-flow-app</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <java.version>17</java.version> <vaadin.version>24.3.8</vaadin.version> <playwright.version>1.43.0</playwright.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.4</version> </parent> </project>
当前使用的XSLT配置
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
期望输出结果
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example.application</groupId> <artifactId>sample-flow-app</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <java.version>17</java.version> <vaadin.version>24.3.8</vaadin.version> <playwright.version>1.43.0</playwright.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.4</version> </parent> </project>
现有Java核心代码
// Read the file and parse to a Document File pomFile = new File("pom.xml"); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(pomFile); // Here I do changes with the Document // Transform the document to a xml string, and write to the filesystem TransformerFactory transformerFactory = TransformerFactory .newInstance(); Transformer transformer = transformerFactory .newTransformer(new StreamSource(IOUtils.toInputStream( """ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> """, "UTF-8"))); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(new FileOutputStream(file)); transformer.transform(source, result);
解决方案
当前XSLT中的<xsl:strip-space elements="*"/>会移除所有空白节点,包括空行对应的文本节点,导致空行丢失。需要调整XSLT逻辑,区分空行和元素内的多余空格:
修改后的XSLT配置
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <!-- 保留空行对应的文本节点:仅含空白字符且包含换行符 --> <xsl:template match="text()[normalize-space(.) = '' and contains(., '
')]"> <xsl:copy/> </xsl:template> <!-- 清理有实际内容的文本节点:去除前后空格,内部多空格合并为单个 --> <xsl:template match="text()[normalize-space(.) != '']"> <xsl:value-of select="normalize-space(.)"/> </xsl:template> <!-- 移除非空行的多余空白节点(比如元素间的缩进空格) --> <xsl:template match="text()[normalize-space(.) = '' and not(contains(., '
'))]"/> <!-- 复制所有其他节点和属性,保证XML结构不变 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
逻辑说明
- 第一个模板专门匹配空行文本节点:这类节点经过
normalize-space处理后为空,但包含换行符,直接复制保留。 - 第二个模板处理有实际内容的文本节点:用
normalize-space清理前后空格,并将内部多个连续空格合并为单个,解决元素内的多余空格问题。 - 第三个模板移除那些既没有实际内容也没有换行的空白节点(比如元素之间的缩进空格),避免产生多余空白。
- 最后一个身份模板负责复制XML的所有元素、属性等节点,保证原有结构完整。
调整Java代码
将Java代码中嵌入的XSLT字符串替换为上述修改后的内容即可,使用Java文本块"""时无需额外转义XML的引号。
内容的提问来源于stack exchange,提问作者Manolo Carrasco Moñino
相关产品推荐
相关产品推荐

