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

如何修改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(., '&#xA;')]">
    <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(., '&#xA;'))]"/>
  
  <!-- 复制所有其他节点和属性,保证XML结构不变 -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

逻辑说明

  1. 第一个模板专门匹配空行文本节点:这类节点经过normalize-space处理后为空,但包含换行符,直接复制保留。
  2. 第二个模板处理有实际内容的文本节点:用normalize-space清理前后空格,并将内部多个连续空格合并为单个,解决元素内的多余空格问题。
  3. 第三个模板移除那些既没有实际内容也没有换行的空白节点(比如元素之间的缩进空格),避免产生多余空白。
  4. 最后一个身份模板负责复制XML的所有元素、属性等节点,保证原有结构完整。

调整Java代码

将Java代码中嵌入的XSLT字符串替换为上述修改后的内容即可,使用Java文本块"""时无需额外转义XML的引号。

内容的提问来源于stack exchange,提问作者Manolo Carrasco Moñino

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 20:14:55