Read nodes of a xml file in C#

前端 未结 1 1972
故里飘歌
故里飘歌 2020-12-02 03:04

How can I read the following xml file into a List:

Partial XML file (data.log)


    <         


        
相关标签:
1条回答
  • 2020-12-02 03:46

    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.

    0 讨论(0)
提交回复
热议问题