First of all, as noted by Jon Skeet in the comments you should probably consider using other tools, like XmlDocument
possibly with LINQ to XML
(EDIT: an example with XmlDocument
follows).
Having said that, here is the simplest solution for what you have currently (note that it's not the cleanest possible code, and it doesn't have much validation):
private static List<XmlTag> ParseElement(XmlReader reader, XmlTag element)
{
var result = new List<XmlTag>() { element };
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
element.IsContainer = true;
var newTag = new XmlTag() { XML_TAG = reader.Name };
if (reader.IsEmptyElement)
{
result.Add(newTag);
}
else
{
result.AddRange(ParseElement(reader, newTag));
}
break;
case XmlNodeType.Text:
element.XML_VALUE = reader.Value;
break;
case XmlNodeType.EndElement:
if (reader.Name == element.XML_TAG)
{
result.Add(new XmlTag()
{
XML_TAG = string.Format("/{0}", reader.Name),
IsContainer = element.IsContainer
});
}
return result;
}
}
return result;
}
private static List<XmlTag> ParseXml(string path)
{
var result = new List<XmlTag>();
using (var reader = XmlReader.Create(path))
{
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
result.AddRange(ParseElement(
reader,
new XmlTag() { XML_TAG = reader.Name }));
}
else if (reader.NodeType == XmlNodeType.EndElement)
{
result.Add(new XmlTag()
{
XML_TAG = string.Format("/{0}",current.Name)
});
}
}
}
return result;
}
An example using XmlDocument
. This will give slightly different result for self-enclosing tags (<description/>
in your case). You can change this behaviour easily, depending on what you want.
private static IEnumerable<XmlTag> ProcessElement(XElement current)
{
if (current.HasElements)
{
yield return new XmlTag()
{
XML_TAG = current.Name.ToString(),
IsContainer = true
};
foreach (var tag in current
.Elements()
.SelectMany(e => ProcessElement(e)))
{
yield return tag;
}
yield return new XmlTag()
{
XML_TAG = string.Format("/{0}", current.Name.ToString()),
IsContainer = true
};
}
else
{
yield return new XmlTag()
{
XML_TAG = current.Name.ToString(),
XML_VALUE = current.Value
};
yield return new XmlTag()
{
XML_TAG = string.Format("/{0}",current.Name.ToString())
};
}
}
And using it:
var xdoc = XDocument.Load(@"test.xml");
var tags = ProcessElement(xdoc.Root).ToList();