By Apple Grinder


2012-12-09 10:21:52 8 Comments

I saw the line below in code for a DOM parser at this tutorial.

doc.getDocumentElement().normalize();

Why do we do this normalization ?
I read the docs but I could not understand a word.

Puts all Text nodes in the full depth of the sub-tree underneath this Node

Okay, then can someone show me (preferably with a picture) what this tree looks like ?

Can anyone explain me why normalization is needed?
What happens if we don't normalize ?

3 comments

@AVA 2016-06-29 07:26:09

In simple, Normalisation is Reduction of Redundancies.
Examples of Redundancies:
a) white spaces outside of the root/document tags(...<document></document>...)
b) white spaces within start tag (<...>) and end tag (</...>)
c) white spaces between attributes and their values (ie. spaces between key name and =")
d) superfluous namespace declarations
e) line breaks/white spaces in texts of attributes and tags
f) comments etc...

@Matas Vaitkevicius 2015-06-18 06:39:18

As an extension to @JBNizet's answer for more technical users here's what implementation of org.w3c.dom.Node interface in com.sun.org.apache.xerces.internal.dom.ParentNode looks like, gives you the idea how it actually works.

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

It traverses all the nodes recursively and calls kid.normalize()
This mechanism is overridden in 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);
 } 

Hope this saves you some time.

@JB Nizet 2012-12-09 13:07:41

The rest of the sentence is:

where only structure (e.g., elements, comments, processing instructions, CDATA sections, and entity references) separates Text nodes, i.e., there are neither adjacent Text nodes nor empty Text nodes.

This basically means that the following XML element

<foo>hello 
wor
ld</foo>

could be represented like this in a denormalized node:

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

When normalized, the node will look like this

Element foo
    Text node: "Hello world"

And the same goes for attributes: <foo bar="Hello world"/>, comments, etc.

@Apple Grinder 2012-12-09 13:12:15

Aha ! its much more clear now. I don't know about data structures (???) and nodes. But I had a quick look at tree structure and, I am guessing that a computer might store "hello world" in the way you suggested. Is that right ?

@JB Nizet 2012-12-09 13:20:44

You need to learn the basics about DOM. Yes, DOM represents an XML document as a tree. And in a tree, you have a root node having child node, each child node also having child nodes, etc. That's what a tree is. Element is a kind of node, and TextNode is another kind of node.

@Apple Grinder 2012-12-09 13:26:07

Thanks JB Nizet. Can't tell you how relieved I am after getting some direction.

@user2043553 2014-06-27 08:10:31

I think your example shouldn't contain newlines: <foo>Hello world</foo>

@Stacky 2014-10-23 15:59:17

@user2043553, the newlines are actually the point there. Without newlines, you wouldn't see the difference. If you shouldn't have understood: Normalization "corrects" the XML so one tag is interpreted as one element. If you didn't do that, it might happen that these very newlines are interpreted as delimiters between several elements of the same type (resp. in the same tag).

@Christian 2015-03-22 19:09:22

@Stacky, in the example there are two new lines, they are not displayed after normalizing in the example which might make people believe there are not there anymore. The resulting text node with newlines displayed would look like: "Hello\nwor\nld" Normalizing does not remove newlines.

@Malwinder Singh 2015-06-04 14:38:38

Why is there Text node: "" in denormalized node?

@JB Nizet 2015-06-04 14:41:27

@M.S. there is not necessarily. The parset is free to parse the text in as many text nodes it wants.

@user3930361 2015-06-19 16:09:36

@JBNizet:is there any way so that i can ensure the tree built in both cases should be same?? Please check stackoverflow.com/questions/30940162/…

Related Questions

Sponsored Content

47 Answered Questions

[SOLVED] Does a finally block always get executed in Java?

41 Answered Questions

[SOLVED] How do I efficiently iterate over each entry in a Java Map?

43 Answered Questions

[SOLVED] How do I convert a String to an int in Java?

28 Answered Questions

[SOLVED] How do I determine whether an array contains a particular value in Java?

  • 2009-07-15 00:03:21
  • Mike Sickler
  • 1884689 View
  • 2184 Score
  • 28 Answer
  • Tags:   java arrays

65 Answered Questions

[SOLVED] How do I generate random integers within a specific range in Java?

  • 2008-12-12 18:20:57
  • user42155
  • 3903299 View
  • 3361 Score
  • 65 Answer
  • Tags:   java random integer

57 Answered Questions

[SOLVED] How do I read / convert an InputStream into a String in Java?

21 Answered Questions

[SOLVED] How do I call one constructor from another in Java?

  • 2008-11-12 20:10:19
  • ashokgelal
  • 806493 View
  • 2134 Score
  • 21 Answer
  • Tags:   java constructor

30 Answered Questions

[SOLVED] How do you parse and process HTML/XML in PHP?

16 Answered Questions

[SOLVED] How do I find out which DOM element has the focus?

  • 2009-01-30 20:21:31
  • Tony Peterson
  • 621871 View
  • 1228 Score
  • 16 Answer
  • Tags:   javascript dom

26 Answered Questions

[SOLVED] How does the Java 'for each' loop work?

Sponsored Content