【问题标题】:C# Parsing Complex XML LINQC# 解析复杂的 XML LINQ
【发布时间】:2016-12-16 00:28:26
【问题描述】:

我一直在尝试成功解析以下 XML 文件。

<?xml version="1.0"?>
<Settings>
    <Tasks>
        <Task ID="1" Name="task_1" Active="1" NextEID="25" AR="0" CacheNames="random">
            <Schedules>
                <Schedule OnlyUntilFirstSuccess="0" FailIfNoSuccessInSched="0" RunEvenIfNotif="0">
                    <Days>
                        <DayOfWeek>Monday</DayOfWeek>
                        <DayOfWeek>Tuesday</DayOfWeek>
                        <DayOfWeek>Wednesday</DayOfWeek>
                        <DayOfWeek>Thursday</DayOfWeek>
                        <DayOfWeek>Friday</DayOfWeek>
                        <DayOfWeek>Saturday</DayOfWeek>
                        <DayOfWeek>Sunday</DayOfWeek>
                    </Days>
                    <Frequency>
                        <Interval StartTime="09:45" EndTime="09:45" EveryMinutes="0"></Interval>
                    </Frequency>
                </Schedule>
            </Schedules>
        </Task>
        <Task ID="2" Name="task_2" Active="1" NextEID="25" AR="0" CacheNames="random">
            <Schedules>
                <Schedule OnlyUntilFirstSuccess="0" FailIfNoSuccessInSched="0" RunEvenIfNotif="0">
                    <Days>
                        <DayOfWeek>Monday</DayOfWeek>
                        <DayOfWeek>Tuesday</DayOfWeek>
                        <DayOfWeek>Wednesday</DayOfWeek>
                        <DayOfWeek>Thursday</DayOfWeek>
                        <DayOfWeek>Friday</DayOfWeek>
                        <DayOfWeek>Saturday</DayOfWeek>
                        <DayOfWeek>Sunday</DayOfWeek>
                    </Days>
                    <Frequency>
                        <Interval StartTime="12:45" EndTime="09:45" EveryMinutes="0"></Interval>
                    </Frequency>
                </Schedule>
            </Schedules>
        </Task>
    </Tasks>
</Settings>

使用网上的几个教程,我拼凑了以下 C# 代码:

public static void ParseXml()
        {
            string strFile = "File.xml";

            XDocument xdoc = XDocument.Load(strFile);

            var tasks = from s in xdoc.Descendants("Tasks")
                        select new
                        {
                            taskID = s.Element("Task").Attribute("ID").Value,
                            taskName = s.Element("Task").Attribute("Name").Value,
                            taskActive = s.Element("Task").Attribute("Active").Value,
                            taskSchedule = s.Element("Task").Element("Schedules").Element("Schedule").Element("Days")
                        };

            foreach (var t in tasks)
            {
                Console.WriteLine("Task Id :: {0}", t.taskID);
                Console.WriteLine("Task Name :: {0}", t.taskName);
                Console.WriteLine("Task Status :: {0}", t.taskActive);
                Console.WriteLine("Task Schedule :: {0}", t.taskSchedule);
            }

            Console.ReadKey();
        }

我的目标是解析出每个任务、任务 ID、名称、天数、频率。我希望最终能够使用这些值在散点图上绘制 TaskID 和 StartTime。我尝试创建以下类,认为它可以帮助我处理文件,但我不知道如何将它们联系在一起。

        public class Task
        {
            public static int taskId { get; set; }
            public static string taskName { get; set; }
        }

        public class Schedule
        {
            public enum DayOfWeek
            {
                Monday,
                Tuesday,
                Wednsday,
                Thursday,
                Friday,
                Saturday,
                Sunday
            }
        }

        public class Frequency
        {
            public static DateTime startTime { get; set; }
            public static DateTime endTime { get; set; }
            public static int everyMins { get; set; }
        }

任何帮助/方向将不胜感激。如果您有解决方案,请不要发布解决方案。请解释一下,以便我可以从中学习并在未来为这个社区做出贡献。

谢谢! 加布

【问题讨论】:

    标签: c# xml linq parsing serialization


    【解决方案1】:

    首先,您需要根据源 XML 构建类。所以有一个Settings 类,其中有Tasks 等等。像这样的东西。当然,我还没有输入所有 XML 属性。但你应该明白要点。您需要 [XMLAttribute] 属性来装饰表示 XML 属性的属性。此外,所有属性名称都区分大小写。所以请确保它们匹配(ID 而不是 Id)。不过,有一些方法可以解决这个问题:

        public class Settings
        {
            public List<Task> Tasks { get; set; }
        }
    
        public class Task
        {
            [XmlAttribute]
            public int ID { get; set; }
    
            [XmlAttribute]
            public string Name { get; set; }
            public List<Schedule> Schedules { get; set; }
    
        }
    
        public class Schedule
        {
            [XmlAttribute]
            public string OnlyUntilFirstSuccess { get; set; }
            public List<DayOfWeek> Days { get; set; }
            public Frequency Frequency { get; set; }
    
        }
        public class Frequency
        {
            public Interval Interval { get; set; }
        }
    
        public class Interval
        {
            [XmlAttribute]
            public string StartTime { get; set; }
            [XmlAttribute]
            public string EndTime { get; set; }
            [XmlAttribute]
            public int EveryMins { get; set; }
        }
    

    然后您可以使用XmlSerializer 将 XML 序列化到您的类。所以你的ParseXml() 方法应该是这样的:

        public static void ParseXml()
        {
            string fileName = "File.xml";
            XDocument xdoc = XDocument.Load(fileName);
            using (TextReader reader = new StringReader(xdoc.ToString()))
            {
                try
                {
                    var settings = (Settings)new XmlSerializer(typeof(Settings)).Deserialize(reader);
                }
                catch (Exception ex)
                {
                    // Handle exceptions as you see fit
                }
            }
        }
    

    其他需要注意的事项:不要命名变量 strxxxxx 来表示它们是字符串,标准约定是公共变量名称以大写字母开头。 此外,您还需要以下内容:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Xml.Linq;
    using System.Xml.Serialization;
    

    【讨论】:

    • 那么,如果我的 XML 文件包含其他元素 \ 属性,我需要为每个元素创建一个类,即使我对整个项目并不关心它们?
    • @Ashwin Nair - 私有变量的约定是什么?那些是小写的吗?而且我经常看到变量名称前带有下划线“_”。下划线代表什么?
    • @ Ashwin Nair - 还有几个问题,我不确定我是否理解您声明频率和间隔类的方式。你能详细说明一下吗?我还看到了代码,其中属性上的装饰器不仅指定对象类型,还指定属性名称,例如: [XMLAttribute("EveryMinutes")] 这是不必要的吗?如果是,为什么?
    • 哇..这是很多问题...好吧..1。您只需要为您感兴趣的元素/属性添加类/属性。请注意,我遗漏了很多属性。同样,例如,如果您没有创建一个名为 Frequency 的类并且没有该属性,它仍然可以正常工作;只有你不会,显然,有data.2。你可以坚持任何你可以接受的约定。我提到的是一个普遍接受的 C# 标准。私有变量通常是camel- cased
    • 另外,我添加了一个频率和间隔类,假设您需要来自您提供的 XML 的相应信息。如果你不需要它,你就不需要使用它。关于您提到的[XMLAttribute("EveryMinutes")] 样式,如果您的属性名称与 XML 中的相应元素/属性不同,则使用它,因此您的 XML 序列化程序知道传入的 XML 属性/元素将被填充到具有该特定名称的属性中.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多