Current Node Position in XmlReader

The XmlReader class provides forward-only access to an XML stream or file. The current node is the XML node on which the reader is currently positioned, and all methods called and actions taken are in relation to that current node, and all properties retrieved reflect the value of the current node.

The reader is advanced by calls to one of the Read methods. The following example shows how you navigate through the stream to determine the current node type.

Option Explicit
Option Strict

Imports System
Imports System.IO
Imports System.Xml

Namespace Test
   
   Public Class MyApp
      
      Public Shared Sub Main()
         Dim rdr As New XmlTextReader("books.xml")
         ReadandWrite(rdr)
      End Sub
      
      Public Shared Sub ReadandWrite(rdr As XmlReader)
         'Read each node in the tree.
         While rdr.Read()
            Select Case rdr.NodeType
               Case XmlNodeType.Element
                  Console.Write(("<" & rdr.Name))
                  While rdr.MoveToNextAttribute()
                     Console.Write((" " & rdr.Name & "='" & rdr.Value & "'"))
                  End While
                  Console.Write(">")
                  If rdr.IsEmptyElement = True Then
                     Console.Write("#EmptyElement")
                  Else
                     Console.Write("#Element")
                  End If
               Case XmlNodeType.Text
                  Console.Write(rdr.Value)
                  Console.Write("#Text")
               Case XmlNodeType.CDATA
                  Console.Write(rdr.Value)
               Case XmlNodeType.ProcessingInstruction
                  Console.Write(("<?" & rdr.Name & " " & rdr.Value & "?>"))
               Case XmlNodeType.Comment
                  Console.Write(("<!--" & rdr.Value & "-->"))
               Case XmlNodeType.Document
                  Console.Write("<?xml version='1.0'?>")
               Case XmlNodeType.Whitespace
                  Console.Write(rdr.Value)
               Case XmlNodeType.SignificantWhitespace
                  Console.Write(rdr.Value)
               Case XmlNodeType.EndElement
                  Console.Write(("</" & rdr.Name & ">"))
                  Console.Write("#EndElement")
            End Select
         End While
      End Sub
   End Class
End Namespace
[C#]using System;
using System.IO;
using System.Xml;
namespace Test
{
   public class MyApp 
   {
     public static void Main()
     {
        XmlTextReader rdr = new XmlTextReader("books.xml");
        ReadandWrite(rdr);
     }
     public static void ReadandWrite(XmlReader rdr)
     {
        //Read each node in the tree.
        while (rdr.Read())
        {
           switch (rdr.NodeType)
           {
             case XmlNodeType.Element:
               Console.Write("<" + rdr.Name);
               while (rdr.MoveToNextAttribute())
                 Console.Write(" " + rdr.Name + "='" + rdr.Value + "'");
                 Console.Write(">");
                 if (rdr.IsEmptyElement == true)
                    Console.Write("#EmptyElement");
                 else
                    Console.Write("#Element");
                 break;
               case XmlNodeType.Text:
                 Console.Write(rdr.Value);
                 Console.Write("#Text");
               break;
               case XmlNodeType.CDATA:
                 Console.Write(rdr.Value);
               break;
               case XmlNodeType.ProcessingInstruction:
                 Console.Write("<?" + rdr.Name + " " + rdr.Value + "?>");
               break;
               case XmlNodeType.Comment:
                 Console.Write("<!--" + rdr.Value + "-->");
               break;
               case XmlNodeType.Document:
                 Console.Write("<?xml version='1.0'?>");
               break;
               case XmlNodeType.Whitespace:
                 Console.Write(rdr.Value);
               break;
               case XmlNodeType.SignificantWhitespace:
                 Console.Write(rdr.Value);
               break;
               case XmlNodeType.EndElement:
                 Console.Write("</" + rdr.Name + ">");
                 Console.Write("#EndElement");
               break;
            }
         }
      }
   }
}

Calling Read repeatedly moves to the next node, and is typically performed inside a while loop.

The properties available in XmlReader are not available on every node type. For example, the IsEmptyElement returns true if the current node is an element and ends with a forward slash character "/>". Calling this property on any other node type returns false, as this property is not applicable to other node types. The following example shows the use of attribute and element properties. It shows how to check if an element has attributes. If the element has an attribute, the example shows how to loop through the attributes using the AttributeCount property.

Public Sub DisplayAttributes(reader As XmlReader)
    If reader.HasAttributes Then
        Console.WriteLine(("Attributes of <" & reader.Name & ">"))
        Dim i As Integer
        For i = 0 To reader.AttributeCount - 1
            reader.MoveToAttribute(i)
            Console.Write(" {0}={1}", reader.Name, reader.Value)
        Next i
        reader.MoveToElement() 'Moves the reader back to the element node.
    End If
End Sub 'DisplayAttributes
[C#]public void DisplayAttributes(XmlReader reader)
{
  if (reader.HasAttributes)
  {
    Console.WriteLine("Attributes of <" + reader.Name + ">");
    for (int i = 0; i < reader.AttributeCount; i++)
    {
      reader.MoveToAttribute(i);
      Console.Write(" {0}={1}", reader.Name, reader.Value);
    }
    reader.MoveToElement(); //Moves the reader back to the element node.
  }
}

When positioned on an element node, the MoveToAttribute methods allow you to navigate through the attribute list of the element. Similarly, when the reader is positioned on an attribute node, a call to the MoveToElement method positions the reader at the element that owns the current attribute node. This is the technique that is used to move back to the element after navigating through its attributes. For a complete list of available methods, see XmlReader Members.

The following example reads an XML stream with a DTD and prints node properties for each node. The example also checks if the node has an attribute by using the HasAttributes property. If there are attributes, the code uses the MoveToNextAttribute method and prints out the attribute name, local name, and namespace URI.

Public Shared Sub Main()
   Dim stream As New StringReader("<!DOCTYPE test [<!ELEMENT test  (item|bar)*><!ELEMENT item (item*)><!ATTLIST item xml:space (default|preserve) #IMPLIED><!ELEMENT bar (#PCDATA|b|i)*><!ELEMENT b (#PCDATA)><!ELEMENT i (#PCDATA)>]> <test> <item> <item xml:space=""preserve"">  <item/>  </item>  </item>  <bar>  <b>This</b>  <i>is</i>  <b>a test</b>  </bar> </test> ")
   Dim myTxtReader As New XmlTextReader(stream)
   Dim myReader As New XmlValidatingReader(myTxtReader)
   myTxtReader.ValidationType = ValidationType.None
   While myReader.Read()
      WriteNodeInfo(myReader)
   End While
End Sub 'Main
 
Private Shared Sub WriteNodeInfo(xmlreader As XmlReader)
   Console.WriteLine("*****************************************************")
   Console.WriteLine()
   Console.WriteLine(("NodeType  = " + xmlreader.NodeType))
   Console.WriteLine(("NodeName  = " + xmlreader.Name))
   Console.WriteLine(("NodeLocalName  = " + xmlreader.LocalName))
   Console.WriteLine(("NodeNamespace  = " + xmlreader.NamespaceURI))
   Console.WriteLine(("NodePrefix  = " + xmlreader.Prefix))
   Console.WriteLine(("NodeHasValue  = " + xmlreader.HasValue))
   Console.WriteLine(("NodeValue = [" + xmlreader.Value + "]"))
   Console.WriteLine(("NodeDepth = " + xmlreader.Depth))
   Console.WriteLine(("IsEmptyElement = " + xmlreader.IsEmptyElement.ToString()))
   Console.WriteLine(("IsDefault = " + xmlreader.IsDefault.ToString()))
   Console.WriteLine(("QuoteChar = " + xmlreader.QuoteChar))
   Console.WriteLine(("XmlSpace = " + xmlreader.XmlSpace))
   Console.WriteLine(("XmlLang = " + xmlreader.XmlLang))
   Console.WriteLine(("AttributeCount = " + xmlreader.AttributeCount))
   Console.WriteLine(("HasAttributes = " + xmlreader.HasAttributes.ToString()))
   Console.WriteLine(("EOF = " + xmlreader.EOF.ToString()))
   Console.WriteLine(("ReadState = " + xmlreader.ReadState.ToString()))
   If xmlreader.HasAttributes Then
      While True = xmlreader.MoveToNextAttribute()
         Console.WriteLine(("AttributeName = " + xmlreader.Name))
         Console.WriteLine(("AttributeLocalName = " + xmlreader.LocalName))
         Console.WriteLine(("AttributeNamespace = " + xmlreader.NamespaceURI))
      End While
   End If
   Console.WriteLine()
   Console.WriteLine("***************************************************")
   Console.WriteLine()
End Sub 'WriteNodeInfo
[C#]public static void Main() {
    StringReader stream = new StringReader ("<!DOCTYPE test [<!ELEMENT test  (item|bar)*><!ELEMENT item (item*)><!ATTLIST item xml:space (default|preserve) #IMPLIED><!ELEMENT bar (#PCDATA|b|i)*><!ELEMENT b (#PCDATA)><!ELEMENT i (#PCDATA)>]> <test> <item> <item xml:space=\"preserve\">  <item/>  </item>  </item>  <bar>  <b>This</b>  <i>is</i>  <b>a test</b>  </bar> </test> ");
    XmlTextReader myTxtReader = new XmlTextReader (stream);
    XmlValidatingReader myReader = new XmlValidatingReader (myTxtReader);
    myTxtReader.ValidationType = ValidationType.None;
    while (myReader .Read())
        WriteNodeInfo(myReader );
}

private static void WriteNodeInfo(XmlReader xmlreader) {
    Console.WriteLine("*****************************************************");
    Console.WriteLine();
    Console.WriteLine("NodeType  = " + xmlreader.NodeType );            
    Console.WriteLine("NodeName  = " + xmlreader.Name);           
    Console.WriteLine("NodeLocalName  = " + xmlreader.LocalName );            
    Console.WriteLine("NodeNamespace  = " + xmlreader.NamespaceURI);       
    Console.WriteLine("NodePrefix  = " + xmlreader.Prefix);          
    Console.WriteLine("NodeHasValue  = " + xmlreader.HasValue);            
    Console.WriteLine("NodeValue = [" + xmlreader.Value +"]");          
    Console.WriteLine("NodeDepth = " + xmlreader.Depth);          
    Console.WriteLine("IsEmptyElement = " + xmlreader.IsEmptyElement.ToString());  
    Console.WriteLine("IsDefault = " + xmlreader.IsDefault.ToString()); 
    Console.WriteLine("QuoteChar = " + xmlreader.QuoteChar);            
    Console.WriteLine("XmlSpace = " + xmlreader.XmlSpace);           
    Console.WriteLine("XmlLang = " + xmlreader.XmlLang);          
    Console.WriteLine("AttributeCount = " + xmlreader.AttributeCount);
    Console.WriteLine("HasAttributes = " + xmlreader.HasAttributes.ToString());
    Console.WriteLine("EOF = " + xmlreader.EOF.ToString());          
    Console.WriteLine("ReadState = " + xmlreader.ReadState.ToString());            
    if (xmlreader.HasAttributes)
    {
      while (true== xmlreader.MoveToNextAttribute())
      {
         Console.WriteLine("AttributeName = "+ xmlreader.Name);
         Console.WriteLine("AttributeLocalName = "+ xmlreader.LocalName);
         Console.WriteLine("AttributeNamespace = "+ xmlreader.NamespaceURI);
      }
    }
    Console.WriteLine();
    Console.WriteLine("***************************************************");
    Console.WriteLine();
}

Output for the first three nodes:

***************************************************

NodeType  = DocumentType
NodeName  = test
NodeLocalName  = test
NodeNamespace  = 
NodePrefix  = 
NodeHasValue  = True
NodeValue = [<!ELEMENT test  (item|bar)*><!ELEMENT item (item*)><!ATTLIST item xml:space (default|preserve) #IMPLIED><!ELEMENT bar (#PCDATA|b|i)*><!ELEMENT b (#PCDATA)><!ELEMENT i (#PCDATA)>]
NodeDepth = 0
IsEmptyElement = False
IsDefault = False
QuoteChar = "
XmlSpace = None
XmlLang = 
AttributeCount = 0
HasAttributes = False
EOF = False
ReadState = Interactive

*************************************************

***************************************************

NodeType  = Whitespace
NodeName  = 
NodeLocalName  = 
NodeNamespace  = 
NodePrefix  = 
NodeHasValue  = True
NodeValue = [ ]
NodeDepth = 0
IsEmptyElement = False
IsDefault = False
QuoteChar = "
XmlSpace = None
XmlLang = 
AttributeCount = 0
HasAttributes = False
EOF = False
ReadState = Interactive

*************************************************

***************************************************

NodeType  = Element
NodeName  = test
NodeLocalName  = test
NodeNamespace  = 
NodePrefix  = 
NodeHasValue  = False
NodeValue = []
NodeDepth = 0
IsEmptyElement = False
IsDefault = False
QuoteChar = "
XmlSpace = None
XmlLang = 
AttributeCount = 0
HasAttributes = False
EOF = False
ReadState = Interactive

*************************************************

For a list of all the node types, see Types of XML Nodes.

See Also

Reading XML with the XmlReader | Property Settings on XmlReader | Object Comparison Using XmlNameTable with XmlReader | Reading Attributes with XmlReader | Reading Element and Attributes Content | Skipping Content with XmlReader | EntityReference Reading and Expansion | Comparing XmlReader to SAX Reader | Reading XML Data with XmlTextReader | Reading Node Trees with XmlNodeReader | Validating XML with XmlValidatingReader | Customized XML Reader Creation | XmlReader Class | XmlReader Members | XmlNodeReader Class | XmlNodeReader Members | XmlTextReader Class | XmlTextReader Members | XmlValidatingReader Class | XmlValidatingReader