WEB DEVELOPER TIPS: TRAVERSING & PRINTING THE DOM TREE OF A HTML ELEMENT

  

Background

  
   
This tutorial contains an example of traversing a DOM element.  It assumes a fairly good understanding of data structures, and also a fair background in JavaScript.

What is DOM?
DOM stands for Document Object Model.  It is an interface that represent the content of a document.  Think of an interface as a structural description of a piece of data.  The official DOM specification is available in www.w3.org.  

In DOM, the data is an html document, and the data structure is a "tree."  The purpose of DOM is to specify an universally accepted interface, so that languages such as JavaScript can access and manipulate the content of a DOM (ie: the content of an an html page) in a consistent manner.   Within a html page, the DOM tree contains elements such as <HEAD>, <TABLE>, <IMG>, and so on.   

For example: in this html page below, the DOM will look like the following: click this link to see the DOM tree.  

 
      
    
Please note that the browser must support DOM and JavaScript must be enabled to run the example.  (The examples were tested on Firefox 1.02, Internet Explorer 6.2, Netscape 7, Netscape 8 on Windows XP).  The tree opens on a new window.  Popup blockers might prevent the window from showing.  On browsers with tabbed Windows (Netscape 8 for example), the tree might be printed on a Tabbed window.
<HTML>
  <HEAD>
    <TITLE>Html Title
    </TITLE>
  </HEAD>
  <BODY>
    <DIV>
      <TABLE>
        <TR>
           <TD>Table cell 1
           </TD>
        </TR> 
        <TR>
           <TD>Table cell 2
           </TD>
        </TR> 
      </TABLE>
    </DIV>
  </BODY>
</HTML>

This is how the tree looks like in two different browsers.  There are slight differences between browsers, as you can see.  While you should be aware of this fact, the elements in the html code (such are the TABLE TR, and TD, above) are present in both.  And most importantly, the structure of both trees are virtually identical.  

Internet Explorer 6 Firefox 1.02
<HTML>
  ¦
  ¦--<HEAD>
  ¦  ¦
  ¦  ¦--<TITLE>
  ¦  ¦   </TITLE>
  ¦   </HEAD>
  ¦
  ¦--<BODY>
  ¦  ¦
  ¦  ¦--<TABLE>
  ¦  ¦  ¦
  ¦  ¦  ¦--<TBODY>
  ¦  ¦  ¦  ¦
  ¦  ¦  ¦  ¦--<TR>
  ¦  ¦  ¦  ¦  ¦
  ¦  ¦  ¦  ¦  ¦--<TD>
  ¦  ¦  ¦  ¦  ¦  ¦
  ¦  ¦  ¦  ¦  ¦  ¦--[unknown tag]
  ¦  ¦  ¦  ¦  ¦  ¦  
  ¦  ¦  ¦  ¦  ¦   </TD>
  ¦  ¦  ¦  ¦   </TR>
  ¦  ¦  ¦  ¦
  ¦  ¦  ¦  ¦--<TR>
  ¦  ¦  ¦  ¦  ¦
  ¦  ¦  ¦  ¦  ¦--<TD>
  ¦  ¦  ¦  ¦  ¦  ¦
  ¦  ¦  ¦  ¦  ¦  ¦--[unknown tag]
  ¦  ¦  ¦  ¦  ¦  ¦  
  ¦  ¦  ¦  ¦  ¦   </TD>
  ¦  ¦  ¦  ¦   </TR>
  ¦  ¦  ¦   </TBODY>
  ¦  ¦   </TABLE>
  ¦   </BODY>
   </HTML>
<HTML>
  ¦
  ¦--<HEAD>
  ¦  ¦
  ¦  ¦--<TITLE>
  ¦  ¦  ¦
  ¦  ¦  ¦--[unknown tag]
  ¦  ¦  ¦  
  ¦  ¦   </TITLE>
  ¦   </HEAD>
  ¦
  ¦--[unknown tag]
  ¦  
  ¦
  ¦--<BODY>
  ¦  ¦
  ¦  ¦--<TABLE>
  ¦  ¦  ¦
  ¦  ¦  ¦--<TBODY>
  ¦  ¦  ¦  ¦
  ¦  ¦  ¦  ¦--<TR>
  ¦  ¦  ¦  ¦  ¦
  ¦  ¦  ¦  ¦  ¦--<TD>
  ¦  ¦  ¦  ¦  ¦  ¦
  ¦  ¦  ¦  ¦  ¦  ¦--[unknown tag]
  ¦  ¦  ¦  ¦  ¦  ¦  
  ¦  ¦  ¦  ¦  ¦   </TD>
  ¦  ¦  ¦  ¦   </TR>
  ¦  ¦  ¦  ¦
  ¦  ¦  ¦  ¦--<TR>
  ¦  ¦  ¦  ¦  ¦
  ¦  ¦  ¦  ¦  ¦--<TD>
  ¦  ¦  ¦  ¦  ¦  ¦
  ¦  ¦  ¦  ¦  ¦  ¦--[unknown tag]
  ¦  ¦  ¦  ¦  ¦  ¦  
  ¦  ¦  ¦  ¦  ¦   </TD>
  ¦  ¦  ¦  ¦   </TR>
  ¦  ¦  ¦   </TBODY>
  ¦  ¦   </TABLE>
  ¦  ¦
  ¦  ¦--[unknown tag]
  ¦  ¦  
  ¦   </BODY>
   </HTML> 

In the DOM terminology, an element is referred as a node.  A node always has a parentNode (unless it's the root node); and a node can have one or more childNodes.  In the above example, let's examine the <HEAD> node.  The parentNode of that <HEAD> node is the <HTML> node; and the firstChild or the childNodes[0] of that <HEAD> node is the <TITLE> node.   

The <HTML> node in the above example does not have a parentNode; such node is  referred as the root node.  

A node may have siblings, which can be retrieved by using prevSibling (prev stands for previous) and nextSibling.  The <TITLE> node, for example, does not have any sibling.  The two <TR> nodes however; are siblings of each other.  

Siblings do not have to be of the same type.  For instance, the <HEAD> node and the <BODY> nodes are siblings.  (In the tree shown above, when 2 nodes are indented on the same level, they're siblings of each other.)  

Notice something here: In the Internet Explorer tree, the prevSibling of the <BODY> node is the <HEAD> node.  However, in the Firefox tree, there's an [unknown] node between the <HEAD> and the <BODY> node.  Thus, when coding, it's sometimes important to do more checking (such as checking for nodeType or nodeName) before making any assumption about the identity of any particular node.

Here are some more important properties of a node.  This list is not exhaustive.

parentNode

the parent node of the current node
childNodes[n] retrieves the n-th child of the current  node
firstChild the first child of the current  node, or nothing if there's none
lastChild the last child of the current  node, or nothing if there's none
nextSibling the next sibling of the current node, or nothing if there's none
prevSibling the previous sibling of the current node, or nothing if there's none 
nodeType the node type, such as "TR", "IMG", "TABLE", etc.
attributes the node's attribute objects
nodeName the name of the node

  

 
 

JavaScript Code to Print the DOM Tree

 
 
Below is an example code that traverses the DOM tree of an html element.  There are two functions: 
  • The function traverseDOMTree is called recursively to traverse an element (a node) until there's no more branch to traverse.  
  • The function printDOMTree accepts an element (a node) and prints out the element's DOM tree.  This function basically opens a new browser window to print output.  It is not as important as traverseDOMTree (the bulk of the concept is in traverseDOMTree).  

The important parts and explanations are marked in blue.  

<SCRIPT LANGUAGE="JavaScript">
<!--
// F. Permadi 2005.
// (C) F. Permadi
// Print DOM tree
////////////////////////////////////////////
// This function traverses the DOM tree of an element and prints the tree.  
// This function called recursively until the DOM tree is fully traversed.
// 
// Parameters:
// - targetDocument is where the tree will be printed into
// - currentElement is the element that we want to print
// - depth is the depth of the current element 
//   (it should be 1 for the initial element)
////////////////////////////////////////////
function traverseDOMTree(targetDocument, currentElement, depth)
{
  if (currentElement)
  {
    var j;
    var tagName=currentElement.tagName;
    // Prints the node tagName, such as <A>, <IMG>, etc
    if (tagName)
      targetDocument.writeln("&lt;"+currentElement.tagName+"&gt;");
    else
      targetDocument.writeln("[unknown tag]");

    // Traverse the tree
    var i=0;
    var currentElementChild=currentElement.childNodes[i];
    while (currentElementChild)
    {
      // Formatting code (indent the tree so it looks nice on the screen)
      targetDocument.write("<BR>\n");
      for (j=0; j<depth; j++)
      {
        // &#166 is just a vertical line
        targetDocument.write("&nbsp;&nbsp;&#166");
      }								
      targetDocument.writeln("<BR>");
      for (j=0; j<depth; j++)
      {
        targetDocument.write("&nbsp;&nbsp;&#166");
      }					
      if (tagName)
        targetDocument.write("--");

      // Recursively traverse the tree structure of the child node
      traverseDOMTree(targetDocument, currentElementChild, depth+1);
      i++;
      currentElementChild=currentElement.childNodes[i];
    }
    // The remaining code is mostly for formatting the tree
    targetDocument.writeln("<BR>");
    for (j=0; j<depth-1; j++)
    {
      targetDocument.write("&nbsp;&nbsp;&#166");
    }			
    targetDocument.writeln("&nbsp;&nbsp;");
    if (tagName)
      targetDocument.writeln("&lt;/"+tagName+"&gt;");
  }
}
////////////////////////////////////////////
// This function accepts a DOM element as parameter and prints
// out the DOM tree structure of the element.
////////////////////////////////////////////
function printDOMTree(domElement, destinationWindow)
{
  // Use destination window to print the tree.  If destinationWIndow is
  //   not specified, create a new window and print the tree into that window
  var outputWindow=destinationWindow;
  if (!outputWindow)
    outputWindow=window.open();

  // make a valid html page
  outputWindow.document.open("text/html", "replace");
  outputWindow.document.write("<HTML><HEAD><TITLE>DOM</TITLE></HEAD><BODY>\n");
  outputWindow.document.write("<CODE>\n");
  traverseDOMTree(outputWindow.document, domElement, 1);
  outputWindow.document.write("</CODE>\n");
  outputWindow.document.write("</BODY></HTML>\n");
  
  // Here we must close the document object, otherwise Mozilla browsers 
  //   might keep showing "loading in progress" state.
  outputWindow.document.close();
}

//-->
</SCRIPT>

Please retain the copyright notice and provide a link back to this site if you use the script.  

To use the script, let's see an example.   If I have this section on my html page:

<DIV ID="myDiv">
<TABLE ID="myTable">
  <TR><TD>Table content</TD>
  <TD>More content</TD>
</TR>
</TABLE>
</DIV>

I can print the DOM tree of that DIV node by calling:

printDOMTree(document.getElementById('myDiv'));

I can also print the DOM tree of the TABLE node  by calling:

printDOMTree(document.getElementById('myTable'));

(Note: the DIV ID is case sensitive in Mozilla browsers; so when calling getElementById(idOfElement), the idOfElement parameter letter casing must match the way it's declared.  For example, if you have a <TABLE ID="myTable">, the id must be typed as 'myTable'; not 'mytable', and not 'MyTable'.)

Conceptual example: DOM Tree Test Page.
Real world example: Highlighting Table Rows (see Option 2).
  

 
     
 

 

 
     

(C) F. Permadi
permadi@permadi.com

<<INDEX>>

Terms of Use