簡體   English   中英

如何使用where子句查詢xml?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM