J'ai vu la ligne ci-dessous dans le code pour un analyseur DOM à ce tutoriel .
doc.getDocumentElement().normalize();
Pourquoi faisons-nous cette normalisation?
J'ai lu le docs mais je ne comprenais pas un mot.
Place tous les nœuds de texte dans toute la profondeur de la sous-arborescence sous ce nœud.
D'accord, alors quelqu'un peut-il me montrer (de préférence avec une photo) à quoi ressemble cet arbre?
Quelqu'un peut-il m'expliquer pourquoi la normalisation est nécessaire?
Que se passe-t-il si nous ne normalisons pas?
Le reste de la phrase est:
où seule la structure (par exemple, des éléments, des commentaires, des instructions de traitement, des sections CDATA et des références d'entité) sépare les nœuds de texte, c'est-à-dire qu'il n'y a ni nœuds de texte adjacents ni nœuds de texte vides.
Cela signifie fondamentalement que l'élément XML suivant
<foo>hello
wor
ld</foo>
pourrait être représenté comme ceci dans un noeud dénormalisé:
Element foo
Text node: ""
Text node: "Hello "
Text node: "wor"
Text node: "ld"
Une fois normalisé, le nœud ressemblera à ceci
Element foo
Text node: "Hello world"
Et il en va de même pour les attributs: <foo bar="Hello world"/>
, les commentaires, etc.
En guise d'extension de la réponse de @ JBNizet pour les utilisateurs plus techniques, voici à quoi ressemble l'implémentation de l'interface org.w3c.dom.Node
dans com.Sun.org.Apache.xerces.internal.dom.ParentNode
, qui vous donne une idée de son fonctionnement réel.
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);
}
Il traverse tous les nœuds de manière récursive et appelle kid.normalize()
Ce mécanisme est annulé dans 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);
}
J'espère que cela vous fait gagner du temps.
En termes simples, la normalisation est la réduction des redondances.
Exemples de redondances:
a) espaces blancs en dehors des balises racine/document (... <document> </ document> ...)
b) des espaces entre les balises de début (<...>) et les balises de fin (</ ...>)
c) espaces entre les attributs et leurs valeurs (c'est-à-dire espaces entre nom de la clé et = ")
d) déclarations d'espace de noms superflues
e) sauts de ligne/espaces dans les textes d'attributs et de balises
f) commentaires etc ...