Normalizacja w parsowaniu DOM w Javie - jak to działa?

Widziałem poniższą linię w kodzie parsera DOM w ten tutorial .

doc.getDocumentElement().normalize();

Dlaczego robimy tę normalizację ?
Przeczytałem dokumenty , ale nie mogłem zrozumieć ani słowa.

Umieszcza wszystkie węzły tekstowe w pełnej głębi drzewa podrzędnego pod tym węzłem

Ok, może mi ktoś pokazać (najlepiej ze zdjęciem) jak to drzewo wygląda ? Czy ktoś może mi wyjaśnić, dlaczego normalizacja jest potrzebna?
Co się stanie, jeśli nie normalizować ?
Author: Xz_awan, 2012-12-09

3 answers

Reszta zdania to:

Gdzie tylko struktura (np. elementy, komentarze, instrukcje przetwarzania, sekcje CDATA i odniesienia do encji) oddziela węzły tekstowe, tzn. nie ma sąsiednich węzłów tekstowych ani pustych węzłów tekstowych.

Oznacza to w zasadzie, że następujący element XML

<foo>hello 
wor
ld</foo>

Może być reprezentowany w ten sposób w zdenormalizowanym węźle:

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

Po znormalizowaniu węzeł będzie wyglądał tak

Element foo
    Text node: "Hello world"

And the same goes dla atrybutów: <foo bar="Hello world"/>, komentarzy itp.

 322
Author: JB Nizet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-14 09:31:20

W uproszczeniu normalizacja to redukcja zwolnień.
Przykłady zwolnień:
a) białe spacje poza znacznikami root/document(......)
b) białe spacje w znaczniku start (...>) I end tag (...>)
c) białe spacje między atrybutami i ich wartościami (tj. spacje pomiędzy nazwą klucza i =")
d) zbędne deklaracje przestrzeni nazw
e) podziały wierszy/białe spacje w tekstach atrybuty i znaczniki
f) komentarze itp...

 5
Author: AVA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-26 15:07:58

Jako rozszerzenie do odpowiedzi @JBNizet dla bardziej technicznych użytkowników oto jak wygląda implementacja org.w3c.dom.Node interfejsu w com.sun.org.apache.xerces.internal.dom.ParentNode, daje ci wyobrażenie, jak to naprawdę działa.

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

Przemierza wszystkie węzły rekurencyjnie i wywołuje kid.normalize()
Mechanizm ten jest nadpisywany w 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);
 } 
Mam nadzieję, że zaoszczędzisz trochę czasu.
 4
Author: Matas Vaitkevicius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-18 06:39:18