Java保存XML文件时元素间重复新增空白行的解决方法
解决Java保存XML多次运行后元素间逐次新增空白行的问题
问题原因
DOM解析器会将XML文件中的空白字符(换行、缩进空格)解析为文本节点,每次保存时,由于开启了Transformer的缩进配置(INDENT="yes"),会再次生成新的缩进空白,原有的空白文本节点被保留,叠加后就出现了元素间逐次新增空白行的现象。
解决方案
方法1:解析XML时忽略空白节点
修改DocumentBuilderFactory的配置,从根源避免空白文本节点被加入DOM树:
public static void main(String[] args) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 开启忽略空白节点,需同时开启命名空间支持才生效 factory.setIgnoringElementContentWhitespace(true); factory.setNamespaceAware(true); try { DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse("src/main/resources/chunkInfo/chunk.xml"); add(document); saveDocument(document, new File("src/main/resources/chunkInfo/chunk.xml")); } catch (Exception e) { e.printStackTrace(); } }
方法2:保存前清理DOM树中的空白文本节点
如果不想修改解析逻辑,可以在保存前手动遍历DOM树,删除空文本节点:
首先添加清理空白的工具方法:
public static void removeWhitespaceNodes(Node node) { NodeList children = node.getChildNodes(); // 倒序遍历避免删除节点后索引错乱 for (int i = children.getLength() - 1; i >= 0; i--) { Node child = children.item(i); // 删除仅包含空白字符的文本节点 if (child.getNodeType() == Node.TEXT_NODE && child.getTextContent().trim().isEmpty()) { node.removeChild(child); } else if (child.getNodeType() == Node.ELEMENT_NODE) { // 递归清理子元素 removeWhitespaceNodes(child); } } }
然后在保存前调用该方法:
public static void main(String[] args) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse("src/main/resources/chunkInfo/chunk.xml"); add(document); // 清理空白节点后再保存 removeWhitespaceNodes(document.getDocumentElement()); saveDocument(document, new File("src/main/resources/chunkInfo/chunk.xml")); } catch (Exception e) { e.printStackTrace(); } }
方法3:优化Transformer缩进配置(辅助)
部分Transformer实现对indent-number属性支持不佳,可以替换为XSLT标准缩进属性,配合前两种方法使用:
public static void saveDocument(Document document, File xmlFile) { TransformerFactory tff = TransformerFactory.newInstance(); try { Transformer tf = tff.newTransformer(); tf.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "chunk.dtd"); tf.setOutputProperty(OutputKeys.INDENT, "yes"); // 使用XSLT的缩进属性替代indent-number tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); tf.transform(new DOMSource(document), new StreamResult(xmlFile)); } catch (TransformerConfigurationException e) { e.printStackTrace(); } catch (TransformerException e) { e.printStackTrace(); } }
验证效果
修改后多次运行程序,XML文件中元素间的空白行不会再逐次新增,新插入的元素格式保持一致。
内容的提问来源于stack exchange,提问作者miniWorld
相关产品推荐
相关产品推荐

