Normalização no DOM analisando com java - como funciona?

240

Eu vi a linha abaixo no código para um analisador DOM neste tutorial .

doc.getDocumentElement().normalize();

Por que fazemos essa normalização?
Eu li os documentos, mas não consegui entender uma palavra.

Coloca todos os nós de texto em toda a profundidade da subárvore abaixo deste nó

Ok, alguém pode me mostrar (de preferência com uma foto) como é essa árvore?

Alguém pode me explicar por que a normalização é necessária?
O que acontece se não normalizarmos?

Moedor de maçã
fonte
Independentemente da sua pergunta, leia a nota no exemplo: "O Analisador DOM é lento e consome muita memória quando carrega um documento XML que contém muitos dados. Considere o analisador SAX como solução para ele, o SAX é mais rápido. que DOM e use menos memória. " .
Wulfgarpro
3
@ wulfgar.pro - Entendo o que você disse. Mas quero entender as coisas que perguntei na pergunta. Também farei a análise do SAX em breve.
Apple Grinder
Pesquisando no google por "normalizar xml" deu alguns resultados que parecem úteis. Parece semelhante à normalização nos bancos de dados.
Apple Grinder
2
@EJP - umm ... ainda não está claro porque não conheço xml em profundidade e só leio algumas páginas introdutórias. BTW, não me entenda mal, você fez exatamente o que o autor do documento fez - usando palavras complexas em vez de inglês simples (simples como uma equipe de pique = fácil de entender). Palavras simples primeiro e jargão depois funcionam melhor para mim.
Apple Grinder
7
Até o momento em que este artigo foi escrito, o site referenciado está fazendo referência a este post do SO. Meu cérebro acabou de lançar um erro de dependência.
Chessofnerd

Respostas:

366

O restante da frase é:

onde apenas a estrutura (por exemplo, elementos, comentários, instruções de processamento, seções CDATA e referências de entidades) separa nós de texto, ou seja, não há nós de texto adjacentes nem nós de texto vazios.

Isso basicamente significa que o seguinte elemento XML

<foo>hello 
wor
ld</foo>

pode ser representado assim em um nó desnormalizado:

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

Quando normalizado, o nó terá esta aparência

Element foo
    Text node: "Hello world"

E o mesmo vale para atributos: <foo bar="Hello world"/>comentários, etc.

JB Nizet
fonte
2
Aha! está muito mais claro agora. Eu não sei sobre estruturas de dados (???) e nós. Mas observei rapidamente a estrutura das árvores e acho que um computador pode armazenar "olá mundo" da maneira que você sugeriu. Isso está certo ?
Apple Grinder
9
Você precisa aprender o básico sobre o DOM. Sim, o DOM representa um documento XML como uma árvore. E em uma árvore, você tem um nó raiz com nó filho, cada nó filho também com nós filho, etc. Isso é o que é uma árvore. Elemento é um tipo de nó e TextNode é outro tipo de nó.
JB Nizet
7
Obrigado JB Nizet. Não posso dizer como estou aliviado depois de receber alguma orientação.
Apple Grinder
2
@ user2043553, as novas linhas são o ponto principal. Sem novas linhas, você não veria a diferença. Se você não deveria ter entendido: A normalização "corrige" o XML para que uma tag seja interpretada como um elemento. Se você não fez isso, pode acontecer que essas novas linhas sejam interpretadas como delimitadores entre vários elementos do mesmo tipo (ou seja, na mesma tag).
Stacky 23/10
1
@Stacky, no exemplo existem duas novas linhas, elas não são exibidas após a normalização no exemplo, o que pode levar as pessoas a acreditar que não existem mais. O nó de texto resultante com as novas linhas exibidas seria semelhante a: "Hello \ nwor \ nld" A normalização não remove as novas linhas.
Christian
10

De maneira simples, Normalização é Redução de Redundâncias.
Exemplos de redundâncias:
a) espaços em branco fora das tags de raiz / documento ( ... <document> </document> ... )
b) espaços em branco nas tags de início (< ... >) e final (</ ... >)
c) espaços em branco entre os atributos e seus valores (ou seja, espaços entre o nome da chave e = " )
d) declarações de espaço para nome supérfluos
e) quebras de linha / espaços em branco nos textos de atributos e tags
f) comentários etc ...

AVA
fonte
7

Como uma extensão da resposta do @ JBNizet para usuários mais técnicos, eis como é a implementação da org.w3c.dom.Nodeinterface com.sun.org.apache.xerces.internal.dom.ParentNode, fornece a idéia de como ela realmente funciona.

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

Atravessa todos os nós recursivamente e chama kid.normalize()
Esse mecanismo é substituído emorg.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);
 } 

Espero que isso economize algum tempo.

Matas Vaitkevicius
fonte