246

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

doc.getDocumentElement().normalize();

我们为什么要进行这种标准化?
我阅读了文档,但我一个字也听不懂。

将所有文本节点放在此节点下的子树的完整深度中

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

谁能解释我为什么需要标准化?
如果我们不规范化会发生什么?

4

3 回答 3

378

剩下的句子是:

其中只有结构(例如元素、注释、处理指令、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"/>,评论等。

于 2012-12-09T13:07:41.923 回答
11

简单来说,标准化就是减少冗余。
冗余示例:
a) 根/文档标签之外的空格 ( ... <document></document> ... )
b) 开始标签 (< ... >) 和结束标签 (</ ... >)
c) 属性及其值之间的空格(即键名=之间的空格)
d) 多余的命名空间声明
e) 属性和标签文本中的换行符/空格
f) 注释等...

于 2016-06-29T07:26:09.130 回答
7

作为@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);
 } 

希望这可以节省您一些时间。

于 2015-06-18T06:39:18.533 回答