[英]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; }
}
是否有处理NO0
, NO1
, NO2
,...元素的标准方法? 我总是可以构建自己的解析器,但是我更喜欢使用标准方法,例如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”标签。 此示例仅在此处有效,您知道这些标签的确切数量。
这种格式非常疯狂。 不幸的是,这意味着您将需要使用XDocument
或XmlDocument
手动解析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.