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

doc.getDocumentElement().normalize();
为什么要进行规范化?


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


好向我展示(最好带有图片)这棵树是什么样的?

谁能解释我为什么需要规范化? />

评论

不管您有什么问题,请阅读示例中的注释:“ DOM解析器很慢,并且在加载包含大量数据的XML文档时会占用大量内存。请考虑使用SAX解析器作为解决方案,SAX更快比DOM占用更少的内存。”

@ wulfgar.pro-我明白你的意思。但是,我想了解我在问题中提出的内容。我还将很快进行SAX解析。

在google上搜索“ normalize xml”会得到一些有用的结果。它看起来类似于数据库中的规范化。

@EJP-嗯...它仍然不清楚,因为我不了解xml的深度,而且我只读了一些介绍性页面。顺便说一句,不要误会我的意思,您确实做到了文档作者的所作所为-使用复杂的单词而不是简单的英语(纯朴的派克员工=易于理解)。首先说简单的话,后来用行话对我来说更好。

在撰写本文时,所引用的网站正在引用此SO帖子。我的大脑刚刚抛出了依赖项错误。

#1 楼

句子的其余部分是:


其中只有结构(例如,元素,注释,处理指令,CDATA部分和实体引用)分隔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"/>,注释等。

评论


啊哈!现在更清楚了。我不了解数据结构(???)和节点。但是我快速浏览了树的结构,并且我猜想计算机可能会按照您建议的方式存储“ hello world”。是对的吗 ?

–苹果研磨机
2012年12月9日在13:12

您需要学习有关DOM的基础知识。是的,DOM将XML文档表示为树。在树中,您有一个具有子节点的根节点,每个子节点也都具有子节点,等等。这就是一棵树。元素是一种节点,而文本节点是另一种节点。

– JB Nizet
2012年12月9日在13:20

感谢JB Nizet。无法告诉您在获得指导后我有多放心。

–苹果研磨机
2012年12月9日下午13:26

@ user2043553,换行实际上就是关键所在。没有换行符,您将看不到区别。如果您不应该了解以下内容:标准化会“更正” XML,因此将一个标签解释为一个元素。如果您不这样做,则可能会将这些非常新的换行符解释为相同类型(分别在同一标记中)的多个元素之间的分隔符。

–堆叠
2014-10-23 15:59



@Stacky,在该示例中有两个新行,在示例中进行归一化后不会显示它们,这可能使人们认为不再存在。结果显示的带有换行符的文本节点如下所示:“ Hello \ nwor \ nld”规范化不会删除换行符。

–基督徒
15年3月22日在19:09

#2 楼

简单来说,归一化是减少冗余。冗余示例:
a)根/文档标签(... ...)
之外的空白b)起始标签(<... >)和结束标记(
c)属性及其值之间的空格(即键名和=“之间的空格) e)属性和标签文本中的换行符/空格
f)注释等...

#3 楼

作为对@JBNizet针对更多技术用户的答案的扩展,以下是org.w3c.dom.Nodecom.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希望这可以节省您一些时间。