October 24, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Reading XML Files with the XmlTextReader Class, Part 2

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

Skipping to Content

Now turn your attention to the issue of content vs. non-content nodes. Contents nodes are nodes of type CDATA, Element, EndElement, EntityReference, or EndEntity. Non-content nodes are everything else—including the declaration, processing instruction, document type, and so on. Once again, you could simply insert conditional logic into your read loop to ignore the unwanted nodes. However, a more efficient technique—and certainly more maintainable should more non-content nodes be defined in the future—is to use the XmlTextReader::MoveToContent method.

The MoveToContent method basically tells the XML parser to jump from the current node to the next content node. One thing to understand is that the MoveToContent method doesn't actually read the node. Its sole responsibility is to jump non-content nodes. Therefore, this method is used in conjunction with the XmlTextReader::Read method to read all content nodes as follows:

// Read only content nodes
for (XmlNodeType nodeType = xmlreader->MoveToContent(); 
     NULL != nodeType; 
     xmlreader->Read(), (nodeType = xmlreader->MoveToContent()))
{
...

Additionally, the following two generic methods (ReadFirstNode and ReadNextNode) allow the caller to specify whether to read the first/next content or non-content node:

// Generic functions to allow caller to specify if first/next
// node should be content node
bool ReadFirstNode(XmlTextReader* xmlreader, bool moveToContent = true)
{
if (moveToContent)
  return (NULL != xmlreader->MoveToContent());
else
  return xmlreader->Read();
}

bool ReadNextNode(XmlTextReader* xmlreader, bool moveToContent = true)
{
  bool bMoreNodes = xmlreader->Read();
  if (bMoreNodes && moveToContent)
    bMoreNodes = (NULL != xmlreader->MoveToContent());

  return bMoreNodes;
}

Using these two functions, the previously presented read loop can now be updated as follows:

// Update of read loop to use ReadFirstNode and ReadNextNode helper methods
XmlTextReader* xmlreader = new XmlTextReader(fileName);
for (bool bMoreNodes = ReadFirstNode(xmlreader); 
     bMoreNodes;
     bMoreNodes = ReadNextNode(xmlreader))
{
  ...
}

Figure 3 shows the results of reading only content nodes that would be applicable for most purposes.


Figure 3: Reading Only "Content" Nodes

Reading Attributes

If you look at the XML file presented at the outset of this article, you'll note that the email element contains two attributes (language and encrypted). However, these items are not displayed in any of the demo application's screen captures. That's because the demo application displays nodes, and attributes are not nodes. Rather, attributes are included within nodes of type element. In order to determine if an element node has attributes, you can use the XmlTextReader::HasAttributes property. If this Boolean property is set to true, you can then use the XmlTextReader::MoveToAttribute method to iteratively move to each attribute defined for the node. The following snippet illustrates how to read the attributes for an element node:
if (xmlreader->NodeType == XmlNodeType::Element
&& xmlreader->HasAttributes)
{
  for (int i = 0; i < xmlreader->AttributeCount; i++)
  {
    xmlreader->MoveToAttribute(i);
    // XmlTextReader::Name will contain the name of the attribute
    // XmlTextReader::Value will contain the value of the attribute
    ...    

Be careful here because when you read nodes and attributes using the XmlTextReader class, you are continually moving a pointer or cursor through the file in a forward-only manner. Therefore, depending on how you're reading your element nodes (I presented several alternatives in the previous article), you'll want to ensure that you read the attributes before the element value, as that's the order in which they appear in a properly formed XML file.

Looking Ahead

The past three articles have covered the basics of creating XML files, reading nodes (including elements and text), parsing for specific node types and values, skipping non-content nodes, and reading attributes. Next week's article will pull all this together and present a step-by-step tutorial for writing a maintenance application using the XmlTextWriter and XmlTextReader classes.

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.

 

 


Sitemap | Contact Us

Rocket Fuel