Home > Articles > Web Services > XML

  • Print
  • + Share This
Like this article? We recommend

Like this article? We recommend

Navigating the DOM

The XmlNode class also provides a standard navigational interface for traversing nodes in a document. Part of the navigation interface listed next is from the DOM specifications; SelectSingleNode and SelectNodes methods are Microsoft extensions that take an XPath statement and return the appropriate node(s).

  • ChildNodes

  • HasChildNodes

  • Attributes

  • FirstChild

  • LastChild

  • NextSibling

  • PreviousSibling

  • ParentNode

  • OwnerDocument

  • SelectSingleNode

  • SelectNodes

To help with navigation among a group of nodes, the DOM specifies two standard node collections: the XmlNodeList for ordered access by position, and the XmlNamedNodeMap for access by position or by name. Nodes use XmlNodeList for collections of child nodes thru the ChildNodes property. Nodes use the XmlAttributesCollection class, which derives from XmlNamedNodeMap, to represent attributes through the Attributes property. The .NET framework makes life easier by providing indexer access to the contents of each type of collection.

The following list shows the XmlNodeList navigation methods:

  • Item

  • Count

Here are the XmlNamedNodeMap navigation methods:

  • GetNamedItem

  • Item

  • Count

Listing 1 shows how to access a child element and a child attribute through the indexer.

Listing 1: Using Indexers Instead of Methods to Access Collection Data

XmlNodeList nodes = GetNodeListFromSomewhere();
Console.WriteLine("Name: {0}",nodes[5].Name);
Console.WriteLine("Attribute ID:{0}", nodes[5].Attributes["ID"].Value);

Now that you have reviewed the basic node navigation and value-retrieval methods of an XmlDocument, you can pull the pieces together and parse a document for structure and information. Listing 3 is an example that loads and navigates through a typical purchase order document. The full text of the PO.xml file is visible in Listing 2. In the main method the XmlDocument node loads PO.xml from the file and calls the WalkNode method with the document element. The code in the WalkNode functions recursively calls itself for the child element nodes and attribute node to walk through each level of the DOM tree to produce the output in Listing 4.

Listing 2: PO.xml

<?xml version="1.0" encoding="utf-8" ?>
<po:PurchaseOrder 
   xmlns:po="http://michalk.com/XmlDOM/PO.xsd" 
   xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <Number>1001</Number>
   <OrderDate>8/12/01</OrderDate>
   <BillToAddress>
     <Street>101 Main Street</Street>
     <City>Charlotte</City>
     <State>NC</State>
     <ZipCode>28273</ZipCode>
   </BillToAddress>
   <ShipToAddress>
     <Street>101 Main Street</Street>
     <City>Charlotte</City>
     <State>NC</State>
     <ZipCode>28273</ZipCode>
   </ShipToAddress>
   <LineItem Name="Computer Desk" Description="Wood desk for computer"
   SKU="12345A123" Price="499.99" Qty="1" />
</po:PurchaseOrder>

Listing 3: PO Navigation Code

using System;
using System.Xml;

namespace XmlDOM
{

class DOMNavTutorial
{
   static void Main(string[] args)
   {
     // load the PO document 
     XmlDocument dom = new XmlDocument();
     dom.Load("C:\\PO.xml");
        
     // walk node using common XmlNode interface
     Console.WriteLine("Walking nodes in document..\n");
     WalkNode(dom.DocumentElement, 0);
   
     // navigate to adjacent nodes from BillToAddress
     XmlNode shiptonode = dom.SelectSingleNode("//BillToAddress");
        NavigateAdjacentNodes(shiptonode);   
   }

   static void WalkNode(XmlNode node, int depth)
   {
     // print out info about the current node
     for (int i=0; i < depth; i++)
        Console.Write("  ");
     Console.WriteLine("Type:{0} Name:{1} Value:{2}",
        node.NodeType, node.Name, node.Value);
        
     // parse all child attribute nodes
     XmlAttributeCollection attrs = node.Attributes;
     if (attrs != null)
     {
        foreach (XmlNode childNode in attrs)
        {
          WalkNode(childNode, depth+1);
        }
     }

     // parse all child element nodes
     XmlNodeList elems = node.ChildNodes;
     foreach (XmlNode childNode in elems)
     {
        WalkNode(childNode, depth+1);
     }
   }

   static void NavigateAdjacentNodes(XmlNode node)
   {
     Console.WriteLine("\nNavigate from node:{0}\n",node.Name);
     Console.WriteLine("First Child: {0}", node.FirstChild.Name);
     Console.WriteLine("Last Child: {0}", node.LastChild.Name);
     Console.WriteLine("Parent Node: {0}", node.ParentNode.Name);
     Console.WriteLine("Previous Sibling: {0}", 
        node.PreviousSibling.Name);
     Console.WriteLine("Next Sibling: {0}", 
        node.NextSibling.Name);
     Console.WriteLine("Owner Document: {0}", 
        node.OwnerDocument.Name);
   }
}

}

Listing 4: Navigating the PO

Walking nodes in document..

Type:Element Name:po:PurchaseOrder Value:
  Type:Attribute Name:xmlns:po Value:http://michalk.com/XmlDOM/PO.xsd
    Type:Text Name:#text Value:http://michalk.com/XmlDOM/PO.xsd
  Type:Attribute Name:xmlns:xsd Value:http://www.w3.org/2001/XMLSchema
    Type:Text Name:#text Value:http://www.w3.org/2001/XMLSchema
  Type:Attribute Name:xmlns:xsi Value:http://www.w3.org/2001/XMLSchema-
instance Type:Text Name:#text Value:http://www.w3.org/2001/XMLSchema- instance Type:Element Name:Number Value: Type:Text Name:#text Value:1001 Type:Element Name:OrderDate Value: Type:Text Name:#text Value:8/12/01 Type:Element Name:BillToAddress Value: Type:Element Name:Street Value: Type:Text Name:#text Value:101 Main Street Type:Element Name:City Value: Type:Text Name:#text Value:Charlotte Type:Element Name:State Value: Type:Text Name:#text Value:NC Type:Element Name:ZipCode Value: Type:Text Name:#text Value:28273 Type:Element Name:ShipToAddress Value: Type:Element Name:Street Value: Type:Text Name:#text Value:101 Main Street Type:Element Name:City Value: Type:Text Name:#text Value:Charlotte Type:Element Name:State Value: Type:Text Name:#text Value:NC Type:Element Name:ZipCode Value: Type:Text Name:#text Value:28273 Type:Element Name:LineItem Value: Type:Attribute Name:Name Value:Computer Desk Type:Text Name:#text Value:Computer Desk Type:Attribute Name:Description Value:Wood desk for computer Type:Text Name:#text Value:Wood desk for computer Type:Attribute Name:SKU Value:12345A123 Type:Text Name:#text Value:12345A123 Type:Attribute Name:Price Value:499.99 Type:Text Name:#text Value:499.99 Type:Attribute Name:Qty Value:1 Type:Text Name:#text Value:1

After the xml document traversal is complete, you traverse from the ShipToAddress element to show off the full range of XmlNode navigational methods in the NavigateAdjacentNodes method. The ShipToAddress node is located in the document using the SelectSingleNode method and an XPath expression. Listing 5 is the resulting output.

Listing 5: Result of Node Traversal Around BillToAddress

Navigate from node:BillToAddress

First Child: Street
Last Child: ZipCode
Parent Node: po:PurchaseOrder
Previous Sibling: OrderDate
Next Sibling: ShipToAddress
Owner Document: #document
  • + Share This
  • 🔖 Save To Your Account