如何反序列化XML元素的编号数组

时间:2013-12-19 08:52:19

标签: c# xml xml-parsing xml-deserialization

我需要反序列化以下XML:

<TIMEWINDOWS>
    <NUMBER>10</NUMBER>
    <NO0>
        <FROM>22-11-2013 08:00:00</FROM>
        <TO>22-11-2013 11:59:00</TO>
    </NO0>
    <NO1>
        <FROM>22-11-2013 12:00:00</FROM>
        <TO>22-11-2013 15:59:00</TO>
    </NO1>
    <NO2>
        <FROM>23-11-2013 08:00:00</FROM>
        <TO>23-11-2013 11:59:00</TO>
    </NO2>
    <NO3>
        <FROM>23-11-2013 12:00:00</FROM>
        <TO>23-11-2013 15:59:00</TO>
    </NO3>
    ...
</TIMEWINDOWS>

我需要的输出是TimeWindow个对象的集合(列表,数组等),例如:

public class TimeWindow
{
    public string From { get; set; }
    public string To { get; set; }
}

是否有标准方式来处理NO0NO1NO2,...元素? 我总是可以构建自己的解析器,但我更喜欢使用标准方法,例如System.Xml.Serialization.XmlSerializer

5 个答案:

答案 0 :(得分:1)

您可以使用LINQ to XML。有点像...

        XDocument doc = XDocument.Load("XMLFile1.xml");
        var result = new List<TimeWindow>();
        foreach (XElement s in doc.Elements().Descendants())
        {
            if (s.Name.ToString().StartsWith("NO"))
            {
                var tw = new TimeWindow {From = (string)s.Element("FROM"), 
                    To = (string)s.Element("TO")};
                result.Add(tw);
            }
        }

您可能希望在FROM和TO元素周围添加一些空值检查,以确保它们存在于数据中。

答案 1 :(得分:0)

可能性如下:

public class TimeWindow
{ 
public int number{get;set;}
public Times NO0 = new Times();
public Times NO1 = new Times();
public Times NO2 = new Times();
public Times NO3 = new Times();
}

public class Times()
{
public string FROM{get;set;}
public string TO{get;set;}
}

如果你有这门课和帮助班,你可以简单地做以下(当然是另一课):

XmlSerializer serializer = new XmlSerializer(typeof(TimeWindow));
TimeWindow timeWindow = (TimeWindow)serializer.Deserialize(new StreamReader(pathToFile));

在此之后,您可以通过

访问(目前“string”格式化)数据
timeWindow.NO0.FROM;

对我来说,这几天前就有效了。 但我只是从脑海里写下来的。

<强> //修改

对不起,我没有意识到有不同数量的“氮氧化物”标签。 此示例仅适用于此ID,您知道这些标记的确切数量。

答案 2 :(得分:0)

这种格式非常疯狂。不幸的是,这意味着您需要使用XDocumentXmlDocument手动解析xml。让我们使用前者,因为它更容易:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace Xmlarrayload
{
    class Program
    {
        static void Main(string[] args)
        {
            var document = XDocument.Parse(@"<TIMEWINDOWS>
    <NUMBER>4</NUMBER>
    <NO0>
        <FROM>22-11-2013 08:00:00</FROM>
        <TO>22-11-2013 11:59:00</TO>
    </NO0>
    <NO1>
        <FROM>22-11-2013 12:00:00</FROM>
        <TO>22-11-2013 15:59:00</TO>
    </NO1>
    <NO2>
        <FROM>23-11-2013 08:00:00</FROM>
        <TO>23-11-2013 11:59:00</TO>
    </NO2>
    <NO3>
        <FROM>23-11-2013 12:00:00</FROM>
        <TO>23-11-2013 15:59:00</TO>
    </NO3>
</TIMEWINDOWS>");

            int number = int.Parse(document.Root.Element("NUMBER").Value);
            TimeWindow[] windows = (TimeWindow[])Array.CreateInstance(typeof(TimeWindow), number);

            for (int i = 0; i < number; i++)
            {
                var element = document.Root.Element(string.Format("NO{0}", i));
                TimeWindow window = new TimeWindow
                {
                    //it is extremely important to use the correct culture (invariant) to parse the dates.
                    To = DateTime.ParseExact(element.Element("TO").Value, "dd-MM-yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat),
                    From = DateTime.ParseExact(element.Element("FROM").Value, "dd-MM-yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat)
                };
                windows[i] = window;
            }
        }
    }

    public class TimeWindow
    {
        public DateTime From { get; set; }
        public DateTime To { get; set; }
    }
}

答案 3 :(得分:0)

没有标准的方法来处理具有不同名称的元素。因为你的xml不是标准的xml。所有相同类型的孩子都应该有相同的名字,否则他们被视为不同的元素。其他信息(如窗口索引)应通过子属性或元素提供,而不是通过元素名称提供:

<TimeWindows number="10"> <!-- actually you don't need number attribute here -->
    <TimeWindow index="1">
        <From>22-11-2013 08:00:00</From>
        <To>22-11-2013 11:59:00</To>
    </TimeWindow>
    <TimeWindow index="2">
        <From>22-11-2013 12:00:00</From>
        <To>22-11-2013 15:59:00</To>
    </TimeWindow>
    <TimeWindow index="3">
        <From>23-11-2013 08:00:00</From>
        <To>23-11-2013 11:59:00</To>
    </TimeWindow>
</TimeWindows>

所以,你应该手动处理,例如通过过滤掉<NUMBER>元素并枚举所有其他元素

var xdoc = XDocument.Load(path_to_xml);
var windows = xdoc.Root.Elements().Where(e => e.Name.LocalName != "NUMBER")
                  .Select(n => new TimeWindow {
                      From = (string)n.Element("FROM"),
                      To = (string)n.Element("TO")
                   }).ToList();

另请考虑在DateTime课程中使用TimeWindow属性,因为它们会保留日期。

答案 4 :(得分:0)

我用来解决这个问题的方法是将它们保存到.xml文件并从.xml文件中检索。检查以下代码:

 private void SaveTimeWindow(TimeWindow[] time, string filePath)
    {
        //Open a file stream 
        System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Create);
        // Create a xml Serializer object
        System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(TimeWindow[]));
        xmlSer.Serialize(fs, time);
        // Close the file stream
        fs.Close();         
    }

如需加载,您可以使用以下内容:

  private static TimeWindow[] LoadTime(string filePath)
        {
            //Open the XML file
            if (System.IO.File.Exists(filePath))
            {
                System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open);

                // First create a xml Serializer object
                System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(TimeWindow[]));
                // Deserialize the Matrix object
                TimeWindow[] time= (TimeWindow[])xmlSer.Deserialize(fs);

                // Close the file stream
                fs.Close();
                return time;
            }
            else
            {
                return null;
            }

        }

然后您可以根据以下内容保存XML:

SaveTimeWindow(TimeWindow, yourPath);

并根据以下内容加载:

TimeWindow[] t = LoadTime(yourPath);