Now that the XmlDocument is loaded, you can navigate its tree structure. Usually, you'll want to skip the XML declaration and other elements in the prolog and start directly at the root node. This can be done by using the DocumentElement property. This property returns the root element of the node tree.
The XmlDocument can be thought of as a node tree with links both down and up the tree. This allows for navigation in all directions: parent to child, child to parent, and sibling to sibling. The XmlNode abstract base class provides several methods for navigating the tree structure.
The XmlNode provides the HasChildNodes property as an easy way to check whether the node is linked to any child nodes. This property returns true if any child nodes are present and false otherwise. If child nodes are present, you can retrieve the list of child nodes by using the ChildNodes property. Listing 11.3 demonstrates how to use these two methods by implementing the recursive version of the depth-first search graph traversal algorithm.
C# void DepthFirst(XmlNode node) { // Visit the node MessageBox.Show("Name: " + node.Name); if(!node.HasChildNodes) { foreach(XmlNode child in node.ChildNodes) DepthFirst(child); } } VB sub DepthFirst( node as XmlNode ) // Visit the node MessageBox.Show( "Name: " & node.Name ) If Not node.HasChildNodes Then Dim i as Int32 For i = 0 To node.ChildNodes.Length DepthFirst( node.ChildNodes(i) ) Next i End If End Sub |
The XmlNode class also provides an item indexer to retrieve its child nodes. The XmlNode indexer takes a string argument that represents the name of the child node to retrieve. Listing 11.4 illustrates how to use this method.
C# XmlDocument doc = new XmlDocument(); doc.LoadXml("<root><child1/><child2/></root>"); Console.WriteLine(doc.DocumentElement["child2"].Name); VB Dim doc = new XmlDocument() doc.LoadXml("<root><child1/><child2/></root>") MessageBox.Show(doc.DocumentElement("child2").Name) |
If you do not know the name of the child node you are searching for or you want to walk all of the child nodes by using a numeric indexer, it is much more convenient to call the XmlNodeList's item indexer property. The ChildNodes property returns an XmlNodeList that holds all of the current node's children. Listing 11.5 rewrites the DepthFirst method from Listing 11.3, using the XmlNodeList's numeric indexer.
C# static void DepthFirst(XmlNode node) { // Visit the node MessageBox.Show("Name: " + node.Name); if(node.HasChildNodes) { for(int i = 0; i < node.ChildNodes.Count; ++i) DepthFirst(node.ChildNodes[i]); } } VB sub DepthFirst(node As XmlNode) ' Visit the node MessageBox.Show("Name: " & node.Name) Dim i as Integer If(node.HasChildNodes) For i = 0 To node.ChildNodes.Count DepthFirst(node.ChildNodes(i)) Next End If End Sub |
The XmlNode class also provides properties for moving directly to the first and last child nodes. The FirstChild property returns the first child in a node's child list. A null reference is returned if the node has no children. LastChild returns the last child node in a node's child list. Again, a null reference is returned if the node has no children. If the node has only one child, then FirstChild and LastChild reference the same node.
The XmlNode class provides the ability to move to the node's siblings. NextSibling returns the node that immediately follows the current node or null if the node is the last in the sibling list. PreviousSibling returns the node that immediately precedes the current node or null if the node is the first in the sibling list.
Listing 11.6 shows how to implement the DepthFirst method from Listing 11.3, using the FirstChild and NextSibling methods.
C# void DepthFirst(XmlNode node) { // Visit the node MessageBox.Show("NodeType: " + node.NodeType); XmlNode child = node.FirstChild; while(child != null) { DepthFirst(child); child = child.NextSibling; } } VB sub DepthFirst(node As XmlNode) ' Visit the node MessageBox.Show("NodeType: " & node.NodeType) XmlNode child = node.FirstChild While(Not child Is Nothing) DepthFirst(child) child = child.NextSibling End While End Sub |
Two additional properties for navigating an XmlDocument tree are ParentNode and OwnerDocument. ParentNode returns the parent of the current node. The root element's parent is the XmlDocument, and the XmlDocument's parent node is null. Any node in the prolog or epilog also returns the XmlDocument as the parent node. The OwnerDocument property returns the XmlDocument to which the current node belongs. Listing 11.7 displays the path from any given node back to the root node.
C# static void Path(XmlNode node) { XmlNode curNode = node; while(true) { MessageBox.Show("Name: " + curNode.Name); if(curNode.ParentNode == node.OwnerDocument) break; curNode = curNode.ParentNode; } } VB sub Path(node As XmlNode) XmlNode curNode = node While(true) MessageBox.Show("Name: " & curNode.Name) If(curNode.ParentNode = node.OwnerDocument) Exit While End If curNode = curNode.ParentNode End While End Sub |
3.145.96.86