在 C# 中读取 xml 文件的节点 [英] Read nodes of a xml file in C#

查看:20
本文介绍了在 C# 中读取 xml 文件的节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将以下 xml 文件读入列表:

<块引用>

部分 XML 文件 (data.log)

<EventType>消息</EventType><DateStamp>10/13/2016 11:15:00 AM</DateStamp><ShortDescription>N/A</ShortDescription><LongDescription>发送所需订单"电子邮件.</LongDescription></ApplicationLogEventObject><ApplicationLogEventObject><EventType>消息</EventType><DateStamp>10/13/2016 11:15:10 AM</DateStamp><ShortDescription>N/A</ShortDescription><LongDescription>分支机构未下订单 - 1018</LongDescription></ApplicationLogEventObject><ApplicationLogEventObject><EventType>消息</EventType><DateStamp>10/13/2016 11:15:10 AM</DateStamp><ShortDescription>N/A</ShortDescription><LongDescription>分支机构未下订单 - 1019</LongDescription></ApplicationLogEventObject>...

<块引用>

这里是数据访问层 (DAL):

public List得到(){尝试{XmlTextReader xmlTextReader = new XmlTextReader(@"C:data.log");列表recordSet = new List();xmlTextReader.Read();而 (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();记录集.添加(记录);}返回记录集;}捕获(异常前){扔前;}}

<块引用>

以及将保存 XML 文件中的子元素的数据类型:

公共类 ApplicationLogEventObject{公共字符串 EventType { 获取;放;}公共日期时间日期戳{获取;放;}公共字符串 ShortDescription { 获取;放;}公共字符串 LongDescription { 获取;放;}}

在我将子节点读入 List 后,我​​想返回它并将其显示在 DataGridView 中.

任何有关此问题的帮助将不胜感激.

解决方案

您的日志文件不是 XML 文档.由于一个 XML 文档必须有一个且只有一个 根元素,所以它是一系列串联的 XML 文档一起.这样一系列的文档可以通过XmlReader 通过设置 XmlReaderSettings.ConformanceLevel == ConformanceLevel.Fragment.这样做后,您可以通读文件并使用 XmlSerializer 如下:

静态列表读取事件(字符串文件名){return ReadObjects(fileName);}静态列表ReadObjects(字符串文件名){var list = new List();var serializer = new XmlSerializer(typeof(T));var settings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment };使用 (var textReader = new StreamReader(fileName))使用 (var xmlTextReader = XmlReader.Create(textReader, settings)){而 (xmlTextReader.Read()){//跳过空格如果(xmlTextReader.NodeType == XmlNodeType.Element){使用 (var subReader = xmlTextReader.ReadSubtree()){var logEvent = (T)serializer.Deserialize(subReader);list.Add(logEvent);}}}}退货清单;}

使用以下版本的ApplicationLogEventObject:

公共类 ApplicationLogEventObject{公共字符串 EventType { 获取;放;}[XmlElement("DateStamp")]公共字符串 DateStampString {得到{//替换为文化上不变的所需格式.返回 DateStamp.ToString(CultureInfo.InvariantCulture);}放{DateStamp = Convert.ToDateTime(value, CultureInfo.InvariantCulture);}}[XmlIgnore]公共日期时间日期戳{获取;放;}公共字符串 ShortDescription { 获取;放;}公共字符串 LongDescription { 获取;放;}}

示例 .Net fiddle.

注意事项:

  • 元素值 10/13/2016 11:15:00 AM 在 XML 中的日期和时间格式不正确,这是 ISO8601.因此,我引入了一个代理 string DateStampString 属性来手动处理您所需格式的转换,然后用 XmlIgnore.

  • 使用ReadSubtree() 防止在 XML 未缩进时读取超过每个根元素末尾的可能性.

  • 根据文档对于 XmlTextReader:

    <块引用>

    从 .NET Framework 2.0 开始,我们建议您改用 System.Xml.XmlReader 类.

    因此我建议用 XmlReader 替换该类型的使用.

  • 你的 的子节点是元素而不是属性,所以 XmlReader.GetAttribute() 不是用于读取它们的合适方法.

  • 鉴于您的日志文件没有在 ISO 8601 中格式化它们的时间,您至少应该确保它们以文化不变的格式进行格式化,以便日志文件可以在具有不同区域设置的计算机之间交换.使用 CultureInfo.InvariantCulture 确保这一点.

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

Partial XML file (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):

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:

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.

Any help regarding this question will be much appreciated.

解决方案

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.

这篇关于在 C# 中读取 xml 文件的节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆