![](/img/trans.png)
[英]“context instance” for a XElement linq to XML query using a where clause
[英]how to query xml with where clause?
我正在使用linq到xml從xmlstring xmlData中提取Station數據列表。 xmldata看起來像這樣:
<Observations>
<Observation>
<Station>ADELONG POST OFFICE</Station>
<DateTime>2010-09-02T00:00:00</DateTime>
<Temperature>19.212989033764689</Temperature>
</Observation>
<Observation>
<Station>ADELONG POST OFFICE</Station>
<DateTime>2010-09-01T00:00:00</DateTime>
<Temperature>28.529448969536205</Temperature>
</Observation>
<Observation>
<Station>ALBURY AIRPORT</Station>
<DateTime>2010-09-01T00:00:00</DateTime>
<Temperature>34.687027630716109</Temperature>
</Observation>
<Observation>
<Station>ALBURY AIRPORT AWS</Station>
<DateTime>2010-09-01T00:00:00</DateTime>
<Temperature>28.131385570453197</Temperature>
</Observation>
</Observations>
我正在嘗試查詢此xmlstring,以僅提取最新日期時間的站點名稱。 我還想獲取最近的溫度。
我定義了一個電台類:
public class Station
{
public string Name { get; set; }
public DateTime MostRecentDate { get; set; }
public decimal LastTemperature { get; set; }
}
如何列出每個站的最新溫度,日期時間和名稱?
我正在ac#控制台應用程序中運行此代碼(完整代碼):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
namespace weatherxml
{
class Program
{
static void Main(string[] args)
{
string xmlData = @"<Observations><Observation><Station>ADELONG POST OFFICE</Station><DateTime>2010-09-02T00:00:00</DateTime><Temperature>19.212989033764689</Temperature></Observation><Observation><Station>ADELONG POST OFFICE</Station><DateTime>2010-09-01T00:00:00</DateTime><Temperature>28.529448969536205</Temperature></Observation><Observation><Station>ALBURY AIRPORT</Station><DateTime>2010-09-01T00:00:00</DateTime><Temperature>34.687027630716109</Temperature></Observation><Observation><Station>ALBURY AIRPORT AWS</Station><DateTime>2010-09-01T00:00:00</DateTime><Temperature>28.131385570453197</Temperature></Observation></Observations>";
XDocument weatherData = XDocument.Parse(xmlData);
var stations = from item in weatherData.Descendants("Observation")
select new Station
{
Name = item.Element("Station").Value,
MostRecentDate = DateTime.Parse(item.Element("DateTime").Value),
LastTemperature = Decimal.Parse(item.Element("Temperature").Value)
};
var st = stations;
foreach (var s in st)
{
Console.WriteLine(s.Name);
}
Console.ReadLine();
}
}
public class Station
{
public string Name { get; set; }
public DateTime MostRecentDate { get; set; }
public decimal LastTemperature { get; set; }
}
}
這是另一個類似於您的StackOverflow問題的鏈接
轉換為您的要求后,您應該具有類似於以下內容的代碼:
var op = from station in stations
group station by station.Name into grp
let recentTimestamp = grp.OrderByDescending(t => t.MostRecentDate).FirstOrDefault()
select recentTimestamp;
您也可以嘗試取消我提供的第二個LINQ查詢,並將它們與您自己的第二個LINQ查詢結合起來,如果您根本只希望選擇最近的項目。
使用Groupby子句
var st =從s組中s的s中的s.Name到結果中,選擇new {Station = result.Key,MostRecent = result.Max(item => item.MostRecentDate)};
foreach (var s in st)
{
Console.WriteLine(s.MostRecent);
Console.WriteLine(s.Station);
}
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
namespace weatherxml
{
class Program
{
static void Main(string[] args)
{
string xmlData = @"<Observations><Observation><Station>ADELONG POST OFFICE</Station><DateTime>2010-09-02T00:00:00</DateTime><Temperature>19.212989033764689</Temperature></Observation><Observation><Station>ADELONG POST OFFICE</Station><DateTime>2010-09-01T00:00:00</DateTime><Temperature>28.529448969536205</Temperature></Observation><Observation><Station>ALBURY AIRPORT</Station><DateTime>2010-09-01T00:00:00</DateTime><Temperature>34.687027630716109</Temperature></Observation><Observation><Station>ALBURY AIRPORT AWS</Station><DateTime>2010-09-01T00:00:00</DateTime><Temperature>28.131385570453197</Temperature></Observation></Observations>";
var stl = new List<Station>();
using (DataSet ds = new DataSet())
{
ds.ReadXml(new StringReader(xmlData));
//i want proper types, not strings
DataColumn dc = ds.Tables[0].Columns.Add("dt", typeof(DateTime));
dc.Expression = "DateTime";
dc = ds.Tables[0].Columns.Add("temp", typeof(Decimal));
dc.Expression = "Temperature";
//group by
var result = ds.Tables[0].AsEnumerable().GroupBy(a => a.Field<string>("Station")).Select(g => g.OrderByDescending(a => a.Field<DateTime>("dt")));
//create result
foreach(var i in result)
{
var fi = i.First();
stl.Add(new Station() { Name = fi.Field<string>("Station"), LastTemperature = fi.Field<decimal>("temp"), MostRecentDate = fi.Field<DateTime>("dt") });
}
//here the stationList (stl) has info for all stations
}
Console.ReadLine();
}
}
public class Station
{
public string Name { get; set; }
public DateTime MostRecentDate { get; set; }
public decimal LastTemperature { get; set; }
}
}
嘗試按站點名稱對數據進行分組,然后從每個組中選擇具有最大日期的觀測值。 此linq查詢應該工作:
var stations = from item in weatherData.Descendants("Observation")
group item by (string) item.Element("Station")
into g
let date = g.Max(o => DateTime.Parse((string)o.Element("DateTime")))
select new
{
Name = g.Key,
MostRecentDate = date,
LastTemperature = Decimal.Parse((string)g.FirstOrDefault(o => date == DateTime.Parse((string)o.Element("DateTime"))).Element("Temperature"))
};
但是這種方式更具可讀性:
var query = from item in weatherData.Descendants("Observation")
group item by (string) item.Element("Station")
into g
select g;
var stations = new List<Station>();
foreach (var q in query)
{
//maximum date in current group
var maxDate = q.Max(o => DateTime.Parse((string) o.Element("DateTime")));
//1st observation having date equal maximum date
var latestObservation = q.FirstOrDefault(o => DateTime.Parse((string) o.Element("DateTime")) == maxDate);
//create new Station using data from latest observation
var newStation = new Station();
newStation.Name = q.Key;
newStation.MostRecentDate = maxDate;
newStation.LastTemperature = Decimal.Parse((string)latestObservation.Element("Temperature"));
//add newly created Station to result list
stations.Add(newStation);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.