简体   繁体   English

在C#中读取xml文件的节点

[英]Read nodes of a xml file in C#

How can I read the following xml file into a List: 如何将以下xml文件读入列表:

Partial XML file (data.log) 部分XML文件(data.log)

<ApplicationLogEventObject>
    <EventType>Message</EventType>
    <DateStamp>10/13/2016 11:15:00 AM</DateStamp>
    <ShortDescription>N/A</ShortDescription>
    <LongDescription>Sending 'required orders' email.</LongDescription>
</ApplicationLogEventObject>
<ApplicationLogEventObject>
    <EventType>Message</EventType>
    <DateStamp>10/13/2016 11:15:10 AM</DateStamp>
    <ShortDescription>N/A</ShortDescription>
    <LongDescription>Branches Not Placed Orders - 1018</LongDescription>
</ApplicationLogEventObject>
<ApplicationLogEventObject>
    <EventType>Message</EventType>
    <DateStamp>10/13/2016 11:15:10 AM</DateStamp>
    <ShortDescription>N/A</ShortDescription>
    <LongDescription>Branches Not Placed Orders - 1019</LongDescription>
</ApplicationLogEventObject>
...

And here is the data access layer (DAL): 这是数据访问层(DAL):

public List<FLM.DataTypes.ApplicationLogEventObject> Get()
    {
        try
        {
            XmlTextReader xmlTextReader = new XmlTextReader(@"C:\data.log");
        List<FLM.DataTypes.ApplicationLogEventObject> recordSet = new List<ApplicationLogEventObject>();

        xmlTextReader.Read();

        while (xmlTextReader.Read())
        {
            xmlTextReader.MoveToElement();
            FLM.DataTypes.ApplicationLogEventObject record = new ApplicationLogEventObject();

            record.EventType = xmlTextReader.GetAttribute("EventType").ToString();
            record.DateStamp = Convert.ToDateTime(xmlTextReader.GetAttribute("DateStamp"));
            record.ShortDescription = xmlTextReader.GetAttribute("ShortDescription").ToString()                    
            record.LongDescription = xmlTextReader.GetAttribute("LongDescription").ToString();

            recordSet.Add(record);
        }
        return recordSet;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

And the Data Types which will hold the child elements from the XML file: 以及将保存XML文件中的子元素的数据类型:

public class ApplicationLogEventObject
{
    public string EventType { get; set; }
    public DateTime DateStamp { get; set; }
    public string ShortDescription { get; set; }
    public string LongDescription { get; set; }
}

After I've read the child nodes into a List I would then like to return it and display it in a DataGridView. 将子节点读入列表后,我想返回它并将其显示在DataGridView中。

Any help regarding this question will be much appreciated. 任何有关此问题的帮助将不胜感激。

Your log file is not an XML document. 您的日志文件不是XML文档。 Since an XML document must have one and only one root element , it's a series of XML documents concatenated together. 由于XML文档必须只有一个根元素 ,因此它是一系列串联在一起的XML文档。 Such a series of documents can be read by XmlReader by setting XmlReaderSettings.ConformanceLevel == ConformanceLevel.Fragment . 这样的一系列文件,可以通过读取XmlReader通过设置XmlReaderSettings.ConformanceLevel == ConformanceLevel.Fragment Having done so, you can read through the file and deserialize each root element individually using XmlSerializer as follows: 这样做之后,您可以使用XmlSerializer来通读文件并分别反序列化每个根元素,如下所示:

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 : 使用以下版本的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 . 样本.Net小提琴

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 . <DateStamp> 10/13/2016 11:15:00 AM <DateStamp>元素值10/13/2016 11:15:00 AM的日期和时间的XML格式不正确,格式为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 . 因此,我引入了一个替代string DateStampString属性来手动处理往返于所需格式的转换,然后用XmlIgnore标记原始的DateTime属性。

  • Using ReadSubtree() prevents the possibility of reading past the end of each root element when the XML is not indented. 当XML不缩进时,使用ReadSubtree()可防止读取超出每个根元素末尾的可能性。

  • According to the documentation for XmlTextReader : 根据XmlTextReader文档

    Starting with the .NET Framework 2.0, we recommend that you use the System.Xml.XmlReader class instead. 从.NET Framework 2.0开始,我们建议您改用System.Xml.XmlReader类。

    Thus I recommend replacing use of that type with XmlReader . 因此,我建议使用XmlReader替换该类型的使用。

  • The child nodes of your <ApplicationLogEventObject> are elements not attributes, so XmlReader.GetAttribute() was not an appropriate method to use to read them. <ApplicationLogEventObject>的子节点不是元素,而是属性,因此XmlReader.GetAttribute()不是用于读取它们的适当方法。

  • 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. 鉴于您的日志文件未按照ISO 8601格式化其时间,因此至少应确保将其格式化为文化上不变的格式,以便可以在具有不同区域设置的计算机之间交换日志文件。 Doing your conversions using CultureInfo.InvariantCulture ensures this. 使用CultureInfo.InvariantCulture转换可确保这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM