XmlReader Made Easy

If you were like me and preferred XmlDocument (before XNA 4.0 compact framework made it disappear) then this snippet should help you. This is a very basic converter that allows you to preload a simple XML file and parse it like a graph instead of the cryptic linear parsings of XmlReader.  Enjoy.

LoadXML() takes an open XmlReader and creates an easy-to-read tree of nodes.  ‘XmlNode’ is a stripped down version of the XmlDocument node, allowing you to easily traverse a node and it’s children, as defined by the XML file.

NOTE: This was a quick a dirty. Attributes are not supported, and there are some O(N) operations that could be optimized out but it worked for my needs.

////////////////////////////////////////////////////////////////////////////////////////
// Example
public static void DoStuff(XmlNode node)
{
	// process node.Name and node.Value based on node.NodeType
 
	// process all of this node's children
	for (XmlNode ch = node.FirstChild; ch != null; ch = ch.NextSibling)
	{
		DoStuff(ch);
	}
}
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
#region Using Statements
using System;
using System.Xml;
using System.Globalization;
using System.Collections.Generic;
using System.Diagnostics;
#endregion
 
namespace GameTools
{
	public static class XMLUtil
	{
		public class XmlNode
		{
			public string Name;
			public string Value;
			public XmlNode FirstChild;
			public XmlNode NextSibling;
			public XmlNodeType NodeType;
		}
 
		private static void AddChild(XmlNode parent, XmlNode child)
		{
			if (parent == null || child == null)
				return;
 
			if (parent.FirstChild == null)
			{
				parent.FirstChild = child;
				return;
			}
 
			XmlNode node = parent.FirstChild;
			while(node.NextSibling != null)
			{
				node = node.NextSibling;
			}
			node.NextSibling = child;
		}
 
		public static XmlNode LoadXML(XmlReader reader)
		{
			XmlNode node = new XmlNode();
			XmlNode child;
 
			// first time entering this function
			if (reader.ReadState == ReadState.Initial)
			{
				// find the xml root element
				while( reader.Read() )
				{
					if (reader.NodeType == XmlNodeType.Element)
						break;
				}
			}
 
			node.Name = reader.Name;
			node.Value = reader.Value;
			node.NodeType = XmlNodeType.Element;
			node.FirstChild = null;
			node.NextSibling = null;
 
			while (reader.Read())
			{
				if (reader.NodeType == XmlNodeType.Element)
				{
					AddChild(node, LoadXML(reader));
				}
				else if (reader.NodeType == XmlNodeType.EndElement)
					break;
				else if (reader.NodeType == XmlNodeType.Text)
				{
					child = new XmlNode();
					child.Name = reader.Name;
					child.Value = reader.Value;
					child.NodeType = XmlNodeType.Text;
					child.FirstChild = null;
					child.NextSibling = null;
 
					AddChild(node, child);
				}
			}
 
			return node;
		}
	}
}

Leave a Reply