Java ile DOM ayrıştırmada normalleştirme - nasıl çalışır?


240

Bu eğitimde bir DOM ayrıştırıcısı için kodda aşağıdaki satırı gördüm .

doc.getDocumentElement().normalize();

Neden bu normalleştirmeyi yapıyoruz? Dokümanları
okudum ama bir kelimeyi anlayamadım.

Tüm Metin düğümlerini bu Düğümün altına alt ağacın tam derinliğine yerleştirir

Tamam, o zaman birisi bana (tercihen bir resim ile) bu ağacın neye benzediğini gösterebilir mi?

Birisi bana neden normalleşmenin gerekli olduğunu açıklayabilir mi?
Normalleşmezsek ne olur?


Sorunuzdan bağımsız olarak, lütfen aşağıdaki örnekteki notu okuyun: "DOM Ayrıştırıcı yavaştır ve çok fazla veri içeren bir XML belgesi yüklediğinde çok fazla bellek tüketir. Lütfen SAX ayrıştırıcısını çözüm olarak düşünün, SAX daha hızlı DOM'dan daha az bellek kullanır. " .
wulfgarpro

3
@ wulfgar.pro - Ne dediğini anlıyorum. Ancak, soruda sorduğum şeyleri anlamak istiyorum. Yakında SAX ayrıştırma da yapacağım.
Apple Grinder

Google'da "normalize xml" araması yararlı görünen bazı sonuçlar verdi. Veritabanlarındaki normalleşmeye benziyor.
Apple Grinder

2
@EJP - umm ... hala net değil çünkü derinlemesine xml bilmiyorum ve sadece birkaç tanıtım sayfası okudum. Btw, beni yanlış anlamayın, tam olarak ne doktor yazar yaptı - düz İngilizce yerine karmaşık kelimeler kullanarak (düz bir pike personel = kolay anlaşılır). Önce basit kelimeler ve daha sonra jargon benim için daha iyi çalışır.
Apple Grinder

7
Bu yazı itibariyle atıfta bulunulan web sitesi bu SO yazısına atıfta bulunuyor. Beynim sadece bir bağımlılık hatası attı.
chessofnerd

Yanıtlar:


366

Cümlenin geri kalanı:

burada yalnızca yapı (ör. öğeler, yorumlar, işleme talimatları, CDATA bölümleri ve varlık referansları) Metin düğümlerini ayırır, yani ne bitişik Metin düğümleri ne de boş Metin düğümleri vardır.

Bu temelde aşağıdaki XML öğesinin

<foo>hello 
wor
ld</foo>

denormalize edilmiş bir düğümde şu şekilde temsil edilebilir:

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

Normalleştirildiğinde, düğüm şöyle görünecektir

Element foo
    Text node: "Hello world"

Aynı şey özellikler için de geçerlidir: <foo bar="Hello world"/>yorumlar, vb.


2
Aha! şimdi çok daha net. Veri yapılarını (???) ve düğümleri bilmiyorum. Ama ağaç yapısına hızlıca baktım ve bir bilgisayarın "merhaba dünyayı" önerdiğiniz şekilde saklayabileceğini tahmin ediyorum. Bu doğru mu ?
Apple Grinder

9
DOM ile ilgili temel bilgileri öğrenmeniz gerekir. Evet, DOM bir XML belgesini ağaç olarak temsil eder. Ve bir ağaçta, alt düğüme sahip bir kök düğümünüz vardır, her bir alt düğümün alt düğümleri de vardır. Bir ağaç budur. Öğe bir tür düğümdür ve TextNode başka bir düğüm türüdür.
JB Nizet

7
Teşekkürler JB Nizet. Biraz yön bulduktan sonra ne kadar rahatlamış olduğumu söyleyemem.
Apple Grinder

2
@ user2043553, yeni satırlar aslında buradaki nokta. Yeni satırlar olmasaydı, farkı göremezdiniz. Eğer anlamamış olsaydınız: Normalizasyon, bir etiketi tek bir öğe olarak yorumlanacak şekilde XML'i "düzeltir". Bunu yapmadıysanız, bu yeni satır satırlarının aynı türden birkaç öğe arasındaki sınırlayıcılar olarak yorumlanması olabilir (aynı etikette sırasıyla.
Stacky

1
@Stacky, örnekte iki yeni satır var, örnekte normalleştikten sonra görüntülenmez, bu da insanları artık orada olmadığına inandırır. Görüntülenen yeni satırların bulunduğu metin düğümü şöyle görünür: "Merhaba \ nwor \ nld" Normalleştirme yeni satırları kaldırmaz.
Hıristiyan

10

Basit olarak, Normalleştirme Fazlalıkların Azaltılmasıdır.
Fazlalıklara Örnekler:
a) kök / belge etiketlerinin dışındaki beyaz boşluklar ( ... <belge> </document> ... )
b) başlangıç ​​etiketi (< ... >) ve bitiş etiketi (</ ... >)
c) öznitelikler ve değerleri arasındaki beyaz boşluklar (örn. anahtar adı ve = " arasındaki boşluklar )
d) gereksiz ad alanı bildirimleri
e) öznitelik ve etiket metinlerindeki satır kesmeleri / beyaz boşluklar
f) yorumlar vb ...


7

@ JBNizet'in daha teknik kullanıcılara verdiği cevabın bir uzantısı olarak, org.w3c.dom.Nodearayüzde nasıl bir uygulama olduğu com.sun.org.apache.xerces.internal.dom.ParentNode, size nasıl çalıştığı hakkında fikir verir.

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

Tüm düğümleri özyinelemeli olarak geçirir ve çağırır. kid.normalize()
Bu mekanizma geçersiz kılınırorg.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);
 } 

Umarım bu size biraz zaman kazandırır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.