Java SAXParser解析XML含<null/>子元素返回空行如何解决
问题原因
该问题由两处逻辑缺陷导致:
- SAX解析器的
characters()方法默认不会过滤标签间的格式空白字符。你给出的XML结构中,<QuotaCode>与<null/>、<null/>与</QuotaCode>之间的换行、缩进空格都会被作为普通字符上报,现有代码收到字符就直接追加到缓存中,最终收集到大量无意义空白,打印时就会出现空行。 - 现有逻辑完全没有处理嵌套
<null/>子标签的能力,既没有识别空值标记的逻辑,也没有在遇到子标签时重置父元素的内容状态,无法区分“元素内容为空(带null子标签)”和“元素包含空白内容”两种场景。
修复方案
按如下逻辑调整代码即可解决问题:
- 新增布尔类型的状态标记,用于标识当前解析的业务字段是否包含
<null/>空值子节点 - 调整
startElement方法逻辑:- 遇到标签名为
null的开始标签时,将空值标记设为true - 遇到业务字段(如
QuotaCode、office_code等)的开始标签时,清空内容缓存,同时将空值标记重置为false
- 遇到标签名为
- 调整
characters方法逻辑:拿到字符片段后先判断是否为纯空白内容(换行、空格、缩进等),如果是直接跳过,不追加到内容缓存中 - 调整
endElement方法的取值逻辑:如果当前字段的空值标记为true,直接将字段值识别为null,不读取缓存内容;如果不是空值,再读取缓存中去除首尾空白的内容作为字段有效值
修复后的完整可运行代码如下:
public class ImportXML2 extends DefaultHandler { private StringBuilder elementValue = new StringBuilder(); // 空值标记位 private boolean isNullValue = false; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { elementValue.setLength(0); if ("null".equals(qName)) { isNullValue = true; } else { isNullValue = false; } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { // 空值场景直接赋值null,非空场景取去空白后的内容 String fieldValue = isNullValue ? null : elementValue.toString().trim(); switch (qName) { case "Total_number_of_packages": System.out.println(fieldValue); break; case "QuotaCode": System.out.println("quote " + (fieldValue == null ? "null" : fieldValue)); break; case "office_code": System.out.println(fieldValue); break; } } @Override public void characters(char[] ch, int start, int length) throws SAXException { // 过滤纯空白的格式字符 String content = new String(ch, start, length); if (content.isBlank()) { return; } elementValue.append(content); } }
调整后解析包含<null/>子标签的节点时,会正确识别为空值,不会再收集无效空白输出多余空行。
内容的提问来源于stack exchange,提问作者Arben Vata
相关产品推荐
相关产品推荐

