3

日付に従ってxmlファイルをフィルタリングするのに助けが必要です。コードのこの部分では、ユーザー名と場所に従ってすべての平均情報のみを出力します

        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>

デビッドのコードを実行すると、次のようなものが出力されます

ユーザー:デビッド

パリの平均距離://データ

マドリードの平均距離: // データ

これは私が望むものではありません。テキストボックスから任意の 2 つの日付を選択して、それらの 2 つの日付の間の情報のみを表示することです。

私は次のようなものを望み、出力します:

ユーザー: デビッド

2012 年 3 月 29 日から 2012 年 8 月 29 日までのパリの平均距離: //data

2012 年 3 月 29 日から 2012 年 8 月 29 日までのマドリッドでの平均距離: //data

私は何時間も試してきましたが、これを実装するのに助けが必要です

4

3 に答える 3

1

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 タグがファイルに存在するかどうか、または値が有効な日付と小数であるかどうかについての有効性チェックは含まれていません。特定のニーズに応じて変更するのはあなた次第です。

于 2012-10-02T04:46:17.817 に答える
1

LINQ to XML を使用します。ここでは、TextBox から選択した 2 つの日付を想定しています。

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)});
}
于 2012-10-02T05:00:25.067 に答える
0

このXml ライブラリを使用すると、日付を読み取って並べ替えることができます。

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();
于 2012-10-02T06:33:21.357 に答える