C# 根据C中的日期从Xml中筛选数据
我需要根据日期筛选xml文件的帮助,因为这部分代码只根据用户名和位置打印出所有平均信息C# 根据C中的日期从Xml中筛选数据,c#,xml,linq,xml-parsing,C#,Xml,Linq,Xml Parsing,我需要根据日期筛选xml文件的帮助,因为这部分代码只根据用户名和位置打印出所有平均信息 Runner run = new Runner(); string filePath = "runners.xml"; //path XDocument xDoc = XDocument.Load(filePath); string userSelect = name; var averageAddDistancequery
Runner run = new Runner();
string filePath = "runners.xml"; //path
XDocument xDoc = XDocument.Load(filePath);
string userSelect = name;
var averageAddDistancequery = xDoc.Descendants("User").Where(w => (string)w.Element("Name") == user).Select(s => new
{
add = s.Elements("Attempts").Where(w => (string)w.Element("Place").Value == "Paris").Select(t => t.Element("Distance").Value)
}).ToList();
if (averageAddDistancequery[0].add.Count() > 0)
{
var aa = averageAddDistancequery[0].add.Average(a => float.Parse(a));
run.averageDistance = aa.ToString();
}
else
{
// nothing
}
var averageAdd2Distancequery = xDoc.Descendants("User").Where(w => (string)w.Element("Name") == userSelector).Select(s => new
{
add = s.Elements("Attempts").Where(w => (string)w.Element("Place").Value == "Madrid").Select(t => t.Element("Distance").Value)
}).ToList();
if (averageAdd2Distancequery[0].add.Count() > 0)
{
var aa = averageAdd2DistanceSubquery[0].add.Average(a => float.Parse(a));
run.averageDistance2 = aa.ToString();
}
else
{
// nothing
}
xmlDoc.DocumentElement.SetAttribute("searching", user);
XmlNodeList tests = xmlDoc.SelectNodes("//User[Name =/*/@searching]/Attempts");
listBox1.Items.Clear();
listBox1.Items.Add("Runners Name: " + user);
listBox1.Items.Add("Overall Distance in Paris: " + run.averageAdd);
listBox1.Items.Add("Overall Distance in Madrid: " + run.averageSub);
例如,如果我的xml文件如下所示
Users>
<User>
<Name>David</Name>
<Attempts>
<Place>Paris</Place>
<Date>3/29/2012</Date>
<Distance>100</Distance>
</Attempts>
<Attempts>
<Place>Madrid</Place>
<Date>7/28/2012</Date>
<Distance>100</Distance>
</Attempts>
<Attempts>
<Place>Paris</Place>
<Date>8/19/2012</Date>
<Distance>60</Distance>
</Attempts>
<Attempts>
<Place>Madrid</Place>
<Date>9/29/2012</Date>
<Distance>200</Distance>
</Attempts>
</User>
<User>
<Name>Lenny</Name>
<Attempts>
<Place>Paris</Place>
<Date>9/29/2012</Date>
<Distance>130</Distance>
</Attempts>
</User>
</Users>
如果我为david运行代码,它会打印出如下内容
Users>
<User>
<Name>David</Name>
<Attempts>
<Place>Paris</Place>
<Date>3/29/2012</Date>
<Distance>100</Distance>
</Attempts>
<Attempts>
<Place>Madrid</Place>
<Date>7/28/2012</Date>
<Distance>100</Distance>
</Attempts>
<Attempts>
<Place>Paris</Place>
<Date>8/19/2012</Date>
<Distance>60</Distance>
</Attempts>
<Attempts>
<Place>Madrid</Place>
<Date>9/29/2012</Date>
<Distance>200</Distance>
</Attempts>
</User>
<User>
<Name>Lenny</Name>
<Attempts>
<Place>Paris</Place>
<Date>9/29/2012</Date>
<Distance>130</Distance>
</Attempts>
</User>
</Users>
用户:大卫
巴黎平均距离://数据
马德里数据中的平均距离
这不是我想要的,我想要的是从文本框中选择任意两个日期,并仅显示这两个日期之间的信息
例如,如果我选择了大卫,从2012年3月29日到2012年8月29日
我想要并输出如下内容:
用户:大卫
巴黎2012年3月29日至2012年8月29日的平均距离://数据
马德里2012年3月29日至2012年8月29日的平均距离://数据
我已经试了好几个小时了,我需要帮助来实现这一点使用Linq to Xml,您可以做您需要做的事情:
XElement x = XElement.Load("In.xml");
IFormatProvider f = new System.Globalization.CultureInfo("en-US");
DateTime bdate = DateTime.Parse("3/29/2012", f);
DateTime edate = DateTime.Parse("8/29/2012", f);
string username = "David";
var info = x.Elements("User")
.Where(u => u.Element("Name").Value == username)
.Select(u => new
{
Name = u.Element("Name").Value, //user name
AverageAttempts = u.Elements("Attempts") //select user's attempts
.Where(a => //filter by dates
{
DateTime d = DateTime.Parse(a.Element("Date").Value, f);
return d >= bdate && d <= edate;
})
.GroupBy(a => a.Element("Place").Value) //group by place
.Select(g => new // create summary info by place
{
Place = g.Key, //place
BeginDate = g.Elements("Date")
.Select(d => DateTime.Parse(d.Value, f))
.Min(), //min date, i.e. first attempt
EndDate = g.Elements("Date")
.Select(d => DateTime.Parse(d.Value, f))
.Max(), //max date, i.e. last attempt
Distance = g.Elements("Distance")//average distance
.Average(d => decimal.Parse(d.Value))
})
})
.FirstOrDefault();
if(info!=null)
{
Console.WriteLine(info.Name);
foreach (var aa in info.AverageAttempts)
{
Console.WriteLine(string.Format("{0} [{1} - {2}]:\t{3}",
aa.Place,
aa.BeginDate,
aa.EndDate,
aa.Distance));
}
}
输出不包含用于筛选的日期,而是用户尝试的实际最小和最大日期
当然,这段代码不包含任何有效性检查,检查文件中是否存在所有必要的xml标记,或者值是否为有效日期和小数……根据您的特定需要,您可以对其进行修改。使用LINQ to xml,在这里假设您从文本框中选择了两个日期:
var userElement = xDox.Descendants("User")
.SingleOrDefault(u => u.Element("Name").Value == "David");
if (userElement != null)
{
var result = userElement.Descendants("Attempts")
.Select(a => new
{
Place = a.Element("Place").Value,
Date = DateTime.Parse(a.Element("Date").Value),
Distance = int.Parse(a.Element("Distance").Value)
})
.Where(a => a.Date >= DateTime.Parse("3/29/2012")
&& a.Date <= DateTime.Parse("8/29/2012"))
.GroupBy(a => a.Place)
.Select(g => new {Place = g.Key, Avg = g.Average(x => x.Distance)});
}
您可以使用它来读取日期并按日期排序
XElement root = XElement.Load(file);
XElement david = root.XPathElement("//User[Name={0}]", "David");
XElement[] attempts = david
.XPath("Attempts[Date>={0} and Date<={1}]",
new DateTime(2012, 3, 29), new DateTime(2012, 8, 29))
.ToArray();
您希望对此使用XQuery。在这里查看它谢谢,它在windows窗体应用程序上工作吗?此外,我需要在文本框中为用户提供一个名称,并且我可以选择我想要的日期,例如,开始日期将在文本框中,结束日期将在另一个文本框中。它还应该一次显示一个用户time@IsraelRodriguez当然会的。你只需要用windows窗体编辑器替换控制台…@IsraelRodriguez我对我的答案做了一点修改,看看我如何在列表框或文本框上显示它?@IsraelRodriguez:它返回列表,循环列表以生成字符串,以便在文本框上显示,如果你不知道,你应该问另一个问题