Read nodes of a xml file in C#
Solution 1:
Your log file is not an XML document. Since an XML document must have one and only one root element, it's a series of XML documents concatenated together. Such a series of documents can be read by XmlReader
by setting XmlReaderSettings.ConformanceLevel == ConformanceLevel.Fragment
. Having done so, you can read through the file and deserialize each root element individually using XmlSerializer
as follows:
static List<ApplicationLogEventObject> ReadEvents(string fileName)
{
return ReadObjects<ApplicationLogEventObject>(fileName);
}
static List<T> ReadObjects<T>(string fileName)
{
var list = new List<T>();
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment };
using (var textReader = new StreamReader(fileName))
using (var xmlTextReader = XmlReader.Create(textReader, settings))
{
while (xmlTextReader.Read())
{ // Skip whitespace
if (xmlTextReader.NodeType == XmlNodeType.Element)
{
using (var subReader = xmlTextReader.ReadSubtree())
{
var logEvent = (T)serializer.Deserialize(subReader);
list.Add(logEvent);
}
}
}
}
return list;
}
Using the following version of ApplicationLogEventObject
:
public class ApplicationLogEventObject
{
public string EventType { get; set; }
[XmlElement("DateStamp")]
public string DateStampString {
get
{
// Replace with culturally invariant desired formatting.
return DateStamp.ToString(CultureInfo.InvariantCulture);
}
set
{
DateStamp = Convert.ToDateTime(value, CultureInfo.InvariantCulture);
}
}
[XmlIgnore]
public DateTime DateStamp { get; set; }
public string ShortDescription { get; set; }
public string LongDescription { get; set; }
}
Sample .Net fiddle.
Notes:
The
<DateStamp>
element values10/13/2016 11:15:00 AM
are not in the correct format for dates and times in XML, which is ISO 8601. Thus I introduced a surrogatestring DateStampString
property to manually handle the conversion from and to your desired format, and then marked the originalDateTime
property withXmlIgnore
.Using
ReadSubtree()
prevents the possibility of reading past the end of each root element when the XML is not indented.-
According to the documentation for
XmlTextReader
:Starting with the .NET Framework 2.0, we recommend that you use the System.Xml.XmlReader class instead.
Thus I recommend replacing use of that type with
XmlReader
. The child nodes of your
<ApplicationLogEventObject>
are elements not attributes, soXmlReader.GetAttribute()
was not an appropriate method to use to read them.Given that your log files are not formatting their times in ISO 8601, you should at least make sure they are formatted in a culturally invariant format so that log files can be exchanged between computers with different regional settings. Doing your conversions using
CultureInfo.InvariantCulture
ensures this.