November 27, 2014
Hot Topics:

Reading XML Files with the XmlTextReader Class

  • May 13, 2005
  • By Tom Archer
  • Send Email »
  • More Articles »

Retrieving Names and Values

Looking at Figure 1, you can see that, to retrieve the value for a given element, you need to look programatically for an node of type XmlNodeType::Text. However, here's the problem. Once you've reached that node, you no longer know the element name for which that text applies becausr that part was read the previous time through the loop. To illustrate what I mean, locate the from element in Figure 1. During that iteration of the loop, what you know is that the NodeType value is XmlNodeType::Element and that its Name property is "from". However, you won't know its value until the next time through the loop when you read the next node, which is the XmlNodeType::Text node for that element. At that point, you can then use the reader's Value property to get the element's text value.

Therefore, there are two ways to read the names and values of the elements you're code needs. One way is to keep track of the current element as you're enumerating the file. Then, when you reach a text node, you'll know for which element the text applies. Here's a code snippet to illustrate how to do that:

// Loop to read the names and values of all elements
String* format = S"{0,-20}{1}";
String* currentElement;

XmlTextReader* xmlreader = new XmlTextReader(fileName);
while (xmlreader->Read())
{
   if (xmlreader->NodeType == XmlNodeType::Element)
   {
    currentElement = xmlreader->Name;
   }
   else if (xmlreader->NodeType == XmlNodeType::Text)
   {
      String* out = String::Format(format,
                                   currentElement,
                                   xmlreader->Value);
      Console::WriteLine(out);
   }
}

Running this code against the test XML file shown earlier yields the results shown in Figure 2 where only the elements are displayed and each element name is properly associated with its value.

Figure 2: Using two reads to get each element's name and value

Keeping in mind that the XmlTextReader is a forward-only reader, there are also methods to tell it what to read next. For example, the XmlTextReader::ReadString method will read the entire contents of the current element or text node into a String object. Here's a loop that illustrates using the ReadString method:

// Loop to read each element's string value
String* format = S"{0,-20}{1}";

XmlTextReader* xmlreader = new XmlTextReader(fileName);
while (xmlreader->Read())
{
   if (xmlreader->NodeType == XmlNodeType::Element)
   {
      String* out = String::Format(format,
                                   xmlreader->Name,
                                   xmlreader->ReadString());
      Console::WriteLine(out);
   }
}

While the ReadString method would seem to be much cleaner than the first approach (of using two distinct reads to obtain the element's name and value), take a look at Figure 3.

Figure 3: Using the ReadString method

As you can see, with this latest modification you now have several blank nodes. This is because the code is no longer looking for an element node followed by a text node—which would indicate an element with text data. Now, the code is simply stating give me the entire string representing each element. In some cases—such as the <emails> node, that node doesn't contain data. Therefore, you need to be careful in knowing what your data is before calling methods such as ReadString.

In most cases where you're looking for a the values of an element, you know the name of that element. Therefore, you would simply insert conditional logic into your code to only call the ReadString method for the desired elements:

if (0 == String::Compare(xmlreader->Name, S"subject", true))
...

Looking Ahead

In this article, you learned how to enumerate XML files using the XmlTextReader class. You also saw code snippets detailing how to parse for specific node types and two different methods for reading the names and values of element nodes. In the next article, I'll cover three more important issues regarding the XmlTextReader class: skipping to content, ignoring whitespace, and reading attributes.

Download the Code

To download the accompanying source code for the demo, click here.

About the Author

Tom Archer owns his own training company, Archer Consulting Group, which specializes in educating and mentoring .NET programmers and providing project management consulting. If you would like to find out how the Archer Consulting Group can help you reduce development costs, get your software to market faster, and increase product revenue, contact Tom through his Web site.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel