W3C Document.parse()解析格式化XML生成多余元素问题求助
问题原因与解决办法
为什么setIgnoringElementContentWhitespace(true)没生效?
setIgnoringElementContentWhitespace(true)的作用是忽略元素内容中的可空白节点,但它的生效有严格前提:
- XML文档必须包含DTD或XML Schema定义;
- 目标元素(这里是
<foo>)被定义为仅包含元素内容(element-only content)——也就是该元素的内容模型明确规定只能有子元素,不能包含任何文本(包括空白字符)。
如果没有DTD/Schema,解析器无法区分“有意义的文本”和“格式化用的空白”,所以即使调用了这个方法,换行、缩进这类空白依然会被解析成文本节点,导致getChildNodes()返回的长度包含这些空白节点。
解决办法
方法1:给XML添加DTD定义
在XML开头添加DTD,明确<foo>只能包含<bar>元素:
<!DOCTYPE main [ <!ELEMENT main (foo)> <!ELEMENT foo (bar+)> <!ELEMENT bar (#PCDATA)> ]> <main> <foo> <bar>1</bar> <bar>2</bar> <bar>3</bar> </foo> </main>
添加后,解析器会根据DTD判断<foo>里的空白是可忽略的,此时getChildNodes()只会返回3个<bar>节点。
方法2:手动过滤空白节点
不需要修改XML,在代码中遍历节点时,只统计元素节点:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); InputStream is = new FileInputStream(FILE_FORMATTED); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(is); NodeList nodes = doc.getElementsByTagName("foo").item(0).getChildNodes(); int barCount = 0; for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); // 只统计元素类型的节点 if (node.getNodeType() == Node.ELEMENT_NODE) { barCount++; } } System.out.println(barCount); // 输出3
方法3:直接统计目标元素(最简便)
跳过遍历子节点的步骤,直接获取<foo>下的所有<bar>元素:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); InputStream is = new FileInputStream(FILE_FORMATTED); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(is); Element fooElement = (Element) doc.getElementsByTagName("foo").item(0); NodeList barNodes = fooElement.getElementsByTagName("bar"); System.out.println(barNodes.getLength()); // 输出3
这种方法无需处理空白节点,直接定位目标元素,结果更可靠。
内容的提问来源于stack exchange,提问作者waxmar
相关产品推荐
相关产品推荐

