使用SAX Parser解析XML时如何精准保留标签内容中的空格?
解决SAX解析XML时的空白保留与多余空白过滤问题
给定XML文件(注意标签前的缩进空白):
<?xml version="1.0" encoding="UTF-8"?> <main> <tagA>190</tagA> <tagB> : </tagB> <tagc>2019-07-02</tagc> </main>预期解析结果:
tagA "190" tagB " : " tagC "2019-07-02"问题:使用SAX的DefaultHandler时,
characters()方法会被多次调用,直接拼接会包含元素间的缩进换行等多余空白;修剪内容会丢失tagB的有效空格,不修剪则tagA、tagC的结果不符合预期;尝试取最后一次characters结果不可靠(大文件内容可能拆分多次),预先线性化文件又担心大文件内存安全。
核心思路
通过跟踪当前是否处于目标元素内部,区分元素间的空白节点(缩进、换行等无效空白)和元素内的文本内容(包括需要保留的有效空白),再针对不同元素应用不同的空白处理规则。
具体实现步骤
- 标记当前元素状态:在自定义Handler中添加布尔变量,标记是否处于需要处理的元素内部。
- 累积元素文本内容:用
StringBuilder实时累积当前元素内的所有字符片段,避免单次characters()调用丢失内容。 - 分元素处理空白:维护一个需要保留原始空白的元素列表,其他元素的内容自动修剪空白,列表内的元素直接保留原始内容。
代码示例
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import java.util.HashSet; import java.util.Set; public class CustomXMLHandler extends DefaultHandler { // 需要保留原始空白的元素集合 private static final Set<String> PRESERVE_WHITESPACES = new HashSet<>(); static { PRESERVE_WHITESPACES.add("tagB"); } private boolean inTargetElement = false; private StringBuilder currentContent = new StringBuilder(); private String currentTagName; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // 进入目标元素时,标记状态并重置内容缓冲区 currentTagName = qName; inTargetElement = true; currentContent.setLength(0); } @Override public void characters(char[] ch, int start, int length) throws SAXException { // 仅当处于目标元素内部时,才累积字符内容 if (inTargetElement) { currentContent.append(ch, start, length); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (inTargetElement) { String content; if (PRESERVE_WHITESPACES.contains(qName)) { // 保留原始空白 content = currentContent.toString(); } else { // 修剪多余空白 content = currentContent.toString().trim(); } // 输出结果(可替换为业务逻辑处理) System.out.printf("%s \"%s\"%n", qName, content); // 重置状态 inTargetElement = false; currentTagName = null; } } }
大文件适配说明
- 每个元素处理完成后立即清空
StringBuilder,不会在内存中累积整个XML文件内容,内存占用始终保持在单个元素内容的量级,完全适配大文件场景。 - 无需预先修改XML文件,避免了大文件读写的额外开销和内存溢出风险。
内容的提问来源于stack exchange,提问作者ilmagowalter
相关产品推荐
相关产品推荐

