繁体   English   中英

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

[英]How to deserialize a numbered array of XML elements

我需要反序列化以下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

您可以使用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元素周围添加一些对null的检查,以确保它们出现在数据中。

一种可能是执行以下操作:

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));

之后,您可以通过访问(当前为“字符串”格式的)数据

timeWindow.NO0.FROM;

对我来说,这在几天前奏效。 但我只是从脑海中写下来。

//编辑

抱歉,我没有意识到有不同数量的“ NOx”标签。 此示例仅在此处有效,您知道这些标签的确切数量。

这种格式非常疯狂。 不幸的是,这意味着您将需要使用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; }
    }
}

没有标准的方法来处理具有不同名称的元素。 因为您的xml不是标准xml。 所有相同类型的子代都应具有相同的名称,否则将它们视为不同的元素。 附加信息(例如window的索引)应通过child的属性或元素提供,而不是通过元素名称提供:

<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();

还应考虑在TimeWindow类中使用DateTime属性,因为它们保存日期。

我用来解决此问题的方法是将它们保存到.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);

暂无
暂无

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

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