如何用where子句查询xml?

时间:2014-03-06 03:36:13

标签: c# linq-to-xml

我正在使用linq to 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; }
}

如何列出每个电台的最新温度+日期时间+名称?

我在c#console应用程序中运行它(完整代码):

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

    }
}

4 个答案:

答案 0 :(得分:0)

这里有Link到另一个类似于你的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查询,并将它们与您自己的相结合,如果您只想要选择最近的项目。

答案 1 :(得分:0)

使用Groupby子句

var st =来自车站的s                          将s.Name分组到结果中                          选择新的{Station = result.Key,MostRecent = result.Max(item =&gt; item.MostRecentDate)};

            foreach (var s in st)
            {
                Console.WriteLine(s.MostRecent);
                Console.WriteLine(s.Station);
            }

答案 2 :(得分:0)

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

    }
}

答案 3 :(得分:0)

尝试按站名对数据进行分组,然后选择具有每组最大日期的观察。这个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);
}