用java解析DOM的规范化——它是如何工作的?

我在本教程的DOM解析器中看到了下面这行代码。

doc.getDocumentElement().normalize();

为什么我们要这么归一化?
我读了文档,但是我一个字也不懂

将所有Text节点放在此Node下面的子树的全深度中

好吧,那谁能给我看看(最好是有照片)这棵树是什么样子的?

谁能解释一下为什么需要正常化?< br >

142891 次浏览

句子的其余部分是:

其中只有结构(例如,元素、注释、处理指令、CDATA节和实体引用)分隔文本节点,即既没有相邻的文本节点也没有空的文本节点。

这基本上意味着下面的XML元素

<foo>hello
wor
ld</foo>

可以在一个非规范化节点中这样表示:

Element foo
Text node: ""
Text node: "Hello "
Text node: "wor"
Text node: "ld"

规范化后,节点看起来是这样的

Element foo
Text node: "Hello world"

属性也是如此:<foo bar="Hello world"/>, comments等等。

作为@JBNizet对更多技术用户的回答的扩展,这里是org.w3c.dom.Node接口在com.sun.org.apache.xerces.internal.dom.ParentNode中的实现,让你了解它实际是如何工作的。

public void normalize() {
// No need to normalize if already normalized.
if (isNormalized()) {
return;
}
if (needsSyncChildren()) {
synchronizeChildren();
}
ChildNode kid;
for (kid = firstChild; kid != null; kid = kid.nextSibling) {
kid.normalize();
}
isNormalized(true);
}
它递归遍历所有节点并调用kid.normalize()
此机制在org.apache.xerces.dom.ElementImpl

中被覆盖
public void normalize() {
// No need to normalize if already normalized.
if (isNormalized()) {
return;
}
if (needsSyncChildren()) {
synchronizeChildren();
}
ChildNode kid, next;
for (kid = firstChild; kid != null; kid = next) {
next = kid.nextSibling;


// If kid is a text node, we need to check for one of two
// conditions:
//   1) There is an adjacent text node
//   2) There is no adjacent text node, but kid is
//      an empty text node.
if ( kid.getNodeType() == Node.TEXT_NODE )
{
// If an adjacent text node, merge it with kid
if ( next!=null && next.getNodeType() == Node.TEXT_NODE )
{
((Text)kid).appendData(next.getNodeValue());
removeChild( next );
next = kid; // Don't advance; there might be another.
}
else
{
// If kid is empty, remove it
if ( kid.getNodeValue() == null || kid.getNodeValue().length() == 0 ) {
removeChild( kid );
}
}
}


// Otherwise it might be an Element, which is handled recursively
else if (kid.getNodeType() == Node.ELEMENT_NODE) {
kid.normalize();
}
}


// We must also normalize all of the attributes
if ( attributes!=null )
{
for( int i=0; i<attributes.getLength(); ++i )
{
Node attr = attributes.item(i);
attr.normalize();
}
}


// changed() will have occurred when the removeChild() was done,
// so does not have to be reissued.


isNormalized(true);
}

希望这能为您节省一些时间。

简单地说,归一化就是减少冗余。< br > 冗余的例子: < br > a)根/文档标记之外的空白(...<document></document>...)
b)开始标记(<...>)和结束标记(</...>)中的空白
C)属性和值之间的空白。键名= "之间的空格)
D)多余的命名空间声明
E)属性和标签文本中的换行符/空格
F)评论等等,