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

问题

我在this tutorial的DOM解析器的代码中看到了下面这一行。

doc.getDocumentElement().normalize();

为什么我们这样做正常化?
我读了docs但我听不懂。

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

好吧,那么有人可以告诉我(最好是带图片)这棵树的样子吗?

任何人都可以解释为什么需要正常化吗?
如果我们不规范化会发生什么?


#1 热门回答(316 赞)

其余的句子是:

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

这基本上意味着以下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"/>,评论等。


#2 热门回答(5 赞)

简单来说,规范化就是减少冗余。
Redundancies示例:
a)根/文档标记之外的空格(... <document> </ document> ...)
b)开始标记(<...>)和结束标记(</ ...>)中的空格
c)属性与其值之间的空格(即之间的空格,密钥名称和**="**")
d)多余的名称空间声明
e)属性和标签文本中的换行符/空格
f)评论等......


#3 热门回答(4 赞)

作为@ JBNizet对更多技术用户的回答的延伸,这里的内容是842515344接口的实现,它可以让你了解它实际上是如何工作的。

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()
这种机制在363171615中被覆盖

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);
 }

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