我需要能够查询xml文档,以便我可以使用与其年份和日期对应的数据填充对象。 XML会不时变化,如果没有报告该年/月的数据点的值,那么它就不会出现在标记中。我仍然想在那个月填充我的对象,但为它插入一个0。
例如,如果xml包含2015年的值和2016年月份3,4,5,6的月份,我将需要一个可以处理这种可变性及其多维度的对象。我需要像[[Year:2015, Months:[1,2,4]],[Year:2016, Months: [3,4,5,6]]]
我想我的问题实际上是两个部分。
1)存储数据变化如此之大的最佳方法是什么。采集?名单?关键值对?多维数组? (我从python和JavaScript转了很多,所以我的术语可能不对)
2)如何查询xml并填充这样的对象。
OBJECT
public class obj1
{
public string[] years { get; set; }
public string[] months { get; set; }
}
XML
<PRODUCTION_SET>
<ENTITY>
<METADATA>
.
.
</METADATA>
<HEADER>
.
.
</HEADER>
<PRODUCTION>
<YEAR NUMBER = "2015">
<MONTH NUMBER = "1">
<DATA1></DATA1>
<DATA2></DATA2>
</MONTH>
<MONTH NUMBER = "2">
<DATA1></DATA1>
<DATA2></DATA2>
</MONTH>
.
.
.
</YEAR>
<YEAR NUMBER = "2016">
<MONTH NUMBER = "1">
<DATA1></DATA1>
<DATA2></DATA2>
</MONTH>
<MONTH NUMBER = "2">
<DATA1></DATA1>
<DATA2></DATA2>
</MONTH>
.
.
.
</YEAR>
</PRODUCTION>
<ENTITY>
</PRODUCTION_SET>
QUERY
public IEnumerable<obj1> queryProduction()
{
return this.doc.Root.Elements("PRODUCING_ENTITY").Select(pe => new obj1{
foreach(var year in pe.Element("PRODUCTION").Elements("YEAR") .....?){
// do stuff to assign months to current year in object.
}
}
}
答案 0 :(得分:1)
试试xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication33
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
obj1.obj1s = doc.Descendants("YEAR").Select(x => new obj1
{
year = (int)x.Attribute("NUMBER"),
month = (int)x.Element("MONTH").Attribute("NUMBER")
}).ToList();
}
}
public class obj1
{
public static List<obj1> obj1s = new List<obj1>();
public int year { get; set; }
public int month { get; set; }
}
}
答案 1 :(得分:1)
您可以将整个事物存储为List,其中Object是用户定义的类型(类),它将具有两个属性,即Year和Months。 Year属性可以是int类型,而Months可以是List。所以基本上它将如下所示:
public class YearStats
{
public int Year { get; set; }
public IList<int> Months { get; set; }
public YearStats()
{
Months = new List<int>();
}
}
如果您需要存储数天的数据,那么您可以将Months的类型更改为IList。同样,这里的对象将是类,其定义与YearStats的定义相同。
您可以使用以下代码段加载数据。
XElement doc = XElement.Load("Test.xml");
IEnumerable<XElement> yearList =
from el in doc.Elements("YEAR")
select el;
List<YearStat> yearData = new List<YearStat>();
foreach (XElement yearEle in yearList)
{
YearStat year = new YearStat();
year.Year = int.Parse((string)yearEle.Attribute("NUMBER"));
var monthList = yearEle.Elements("Month");
List<int> monthData = new List<int>();
foreach(XElement monthEle in monthList)
{
monthData.Add(int.Parse((string)monthEle.Attribute("NUMBER")));
}
year.Months = monthData;
yearData.Add(year);
}
答案 2 :(得分:1)
如果您正在寻找灵活性和可伸缩性,我会为Month和Year对象创建特定的类。此外,.NET使XML序列化和反序列化更容易,因此不需要大量代码。如果您正在寻找性能,那么更简单的对象数据类型可能是更好的选择。
所以,我会创建这样的东西(这可能充满了语法错误,在记事本上做了,对不起):
[Serializable()]
public class Production
{
public Year[] Years {get;set;}
}
[Serializable()]
public class Year
{
public int YearNumber {get;set;}
public int SomeData1 {get;set;}
public int SomeData2 {get;set;}
public Month[] Months {get;set;}
}
[Serializable()]
public class Month
{
public int MonthNumber {get;set;}
public int SomeData1 {get;set;}
public int SomeData2 {get;set}
public Month()
{
// Default value for data - Although integer variables already default to 0,
// so there is no need to do this explicitly
this.SomeData1 = 0
this.SomeData2 = 0
}
}
两个评论:
1)我建议您将月份和年份数字作为数字类型处理,以便能够更轻松地从代码中使用它。
2)我使用[Serializable()]属性将我的类标记为可序列化,因此您应该使用XmlSerializer对象来实现对象的查询和填充。反序列化看起来像这样:
XmlSerializer serializer = new XmlSerializer(typeof(Production), new XmlRootAttribute ("Production"));
FileStream fs = new FileStream(filename, FileMode.Open);
Production prod = (Production) serializer.Deserialize(fs);
一般来看XML serialization with .NET,您可以根据需要轻松或复杂地使用它,它是.NET框架提供的一个非常强大的工具。
答案 3 :(得分:1)
似乎我们很多人都在考虑类似的解决方案......
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace QueryingXML_41271961
{
class Program
{
static void Main(string[] args)
{
string thePath = @"M:\StackOverflowQuestionsAndAnswers\QueryingXML_41271961\QueryingXML_41271961\sample.xml";
XDocument theXMLDoc = XDocument.Load(thePath);
List<XElement> theYears = theXMLDoc.Descendants("PRODUCTION").Elements("YEAR").ToList();
List<InfoHolder> mylist = new List<InfoHolder>();
foreach (XElement yearInXML in theYears)
{
InfoHolder ih = new InfoHolder();
ih.years = yearInXML.Attribute("NUMBER").Value;
foreach (XElement monthsInYear in yearInXML.Elements("MONTH"))
{
if (ih.months == null)
{
ih.months = monthsInYear.Attribute("NUMBER").Value;
}
else
{
ih.months += "," + monthsInYear.Attribute("NUMBER").Value;
}
}
mylist.Add(ih);
}
System.Diagnostics.Debugger.Break();
}
}
public class InfoHolder
{
public string years { get; set; }
public string months { get; set; }
}
}