How can I read the following xml file into a List:
Partial XML file (data.log)
<
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 values 10/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 surrogate string DateStampString
property to manually handle the conversion from and to your desired format, and then marked the original DateTime
property with XmlIgnore.
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, so XmlReader.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.