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

App*_*der 230 java xml computer-science dom

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

doc.getDocumentElement().normalize();
Run Code Online (Sandbox Code Playgroud)

为什么我们这样做正常化?
我读了文档,但我听不懂.

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

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

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

JB *_*zet 354

其余的句子是:

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

这基本上意味着以下XML元素

<foo>hello 
wor
ld</foo>
Run Code Online (Sandbox Code Playgroud)

可以在非规范化节点中表示如下:

Element foo
    Text node: ""
    Text node: "Hello "
    Text node: "wor"
    Text node: "ld"
Run Code Online (Sandbox Code Playgroud)

规范化后,节点将如下所示

Element foo
    Text node: "Hello world"
Run Code Online (Sandbox Code Playgroud)

属性也是如此:<foo bar="Hello world"/>评论等.

  • 您需要学习有关DOM的基础知识.是的,DOM将XML文档表示为树.在树中,您有一个具有子节点的根节点,每个子节点也有子节点等.这就是树.Element是一种节点,TextNode是另一种节点. (9认同)
  • 谢谢JB Nizet.在得到一些方向后,我无法告诉你我是多么放心. (7认同)
  • 啊哈!它现在更清楚了.我不知道数据结构(???)和节点.但我快速浏览一下树形结构,我猜测计算机可能会按照你建议的方式存储"hello world".是对的吗 ? (2认同)
  • @ user2043553,换行实际上就是那里的重点.没有换行符,你就不会看到差异.如果你不应该理解:规范化"纠正"XML,因此一个标记被解释为一个元素.如果你不这样做,可能会发生这些非常新的行被解释为相同类型的几个元素之间的分隔符(在相同的标记中). (2认同)

Mat*_*ius 6

作为@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);
}
Run Code Online (Sandbox Code Playgroud)

它以递归方式遍历所有节点并调用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);
 } 
Run Code Online (Sandbox Code Playgroud)

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


AVA*_*AVA 6

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