Ok let say i have the following xml file

<Users>
  <User>
    <Name>David</Name>
    <Attempts>
      <Place>Paris</Paris
      <Date>3/29/2012</Date>
      <Duration>50 seconds</Duration>
      <Distance>100</Distance>
    </Attempts>
    <Attempts>
      <Place>New York</Paris
      <Date>7/28/2012</Date>
      <Duration>30 seconds</Duration>
      <Distance>100</Distance>
    </Attempts>
   <Attempts>
      <Place>Paris</Paris
      <Date>8/19/2012</Date>
      <Duration>70 seconds</Duration>
      <Distance>60</Distance>
    </Attempts>
    <Attempts>
      <Place>New York</Paris
      <Date>9/29/2012</Date>
      <Duration>60 seconds</Duration>
      <Distance>200</Distance>
    </Attempts>  
  </User>
  <User>
    <Name>Lenny</Name>
     <Attempts>
      <Place>Paris</Paris
      <Date>9/29/2012</Date>
      <Duration>51 seconds</Duration>
      <Distance>130</Distance>
    </Attempts>
  </User>
</Users>

So what im trying to find is particular data between 2 time frames depending on what user i chose from a drop down list

Let Say i chose Daniel and i chose a timeframe from a starttextbox to be 2/20/12 and a endtextbox to be 9/30/12 So what i want is a listbox that will display the following

User: Daniel

Information from 2/20/12 to 9/30/12

Average Distance from Paris:80

Average Distance form New York:150

Average Duration from Paris:60 seconds

Average Duration from New York:45 seconds

Total Duration:105 seconds

Total Distance:230

Is this possible to do? If so i need help to do so, any help would be greatly appreciated

Dani AI

Generated

Quick practical note: the XML in the original post is malformed (several Place nodes are closed as </Paris and some brackets are missing). That must be fixed before any parsing. was right to point toward LINQ-to-XML; ’s sample had multiple syntax and logic mistakes that called out. The approach below assumes valid XML and shows a safe, repeatable way to select a user, filter Attempts by date range, and compute per-Place averages plus totals.

Algorithm (high level): 1) load and locate the chosen User node; 2) parse and normalize each Attempts entry (Date -> DateTime, Distance -> int/double, Duration -> seconds or TimeSpan); 3) filter attempts by the start/end dates; 4) group by Place and compute Average(Distance), Average(Duration), and global totals; 5) format results for the listbox. Important parsing details: use DateTime.TryParse/TryParseExact with an explicit CultureInfo for ambiguous date formats, and normalize Duration strings (e.g., extract numeric seconds or support hh:mm:ss).

Example LINQ-to-XML sketch (compact, original):

using System.Text.RegularExpressions;
using System.Xml.Linq;

var doc = XDocument.Load(path);
var user = doc.Root.Elements("User")
    .FirstOrDefault(u => string.Equals((string)u.Element("Name"), selectedName, StringComparison.OrdinalIgnoreCase));
if (user == null) return;

var attempts = user.Elements("Attempts")
    .Select(a => {
        DateTime.TryParse((string)a.Element("Date"), out var dt);
        int.TryParse((string)a.Element("Distance"), out var dist);
        var durText = ((string)a.Element("Duration") ?? "");
        var m = Regex.Match(durText, @"(\d+)");
        var secs = m.Success ? int.Parse(m.Groups[1].Value) : 0;
        return new { Place = (string)a.Element("Place"), Date = dt, Distance = dist, Seconds = secs };
    })
    .Where(x => x.Date >= startDate && x.Date <= endDate)
    .ToList();

var byPlace = attempts.GroupBy(a => a.Place)
    .Select(g => new { Place = g.Key, AvgDistance = g.Average(a => a.Distance), AvgDurationSeconds = g.Average(a => a.Seconds) });
var totalDistance = attempts.Sum(a => a.Distance);
var totalSeconds = attempts.Sum(a => a.Seconds);

Troubleshooting/cautions: handle missing elements and malformed values with TryParse; if Duration can be "mm:ss" or include units, use a more robust parser or TimeSpan.TryParse; for very large XML use a streaming XmlReader or persist data to a database. This yields the averages per Place and the totals you listed (Average Distance/Duration per place, Total Distance, Total Duration).

Recommended Answers

All 4 Replies

You can always give LINQ to XML a try. Another options is to read the XML file with the System.Xml.Linq.XDocument.Load() or System.Xml.XmlDocument.Load() method, locate the User node, and iterate through each of the Attempts nodes (checking dates and adding the Distance, Duration and number of nodes per Place). Give it a go, and post here again if you have any specific issues.

As I can see, the XML file is well formated.

var source = XElement.Load(MyFile)

var Query = from User in source.Descendents("User")

             where source.Element("Name").Value > "David"

             select new {Id = (int32)User.Element("Name").Value,

                              title = (string)User.Element("Attempts").Element("Date").Value}
commented: Please don't give out answers, especially wrong ones, to people who have not shown any attempt yet. -1

Please don't give out answers, especially wrong ones, to people who have not shown any attempt yet.

As I can see, the XML file is well formated.

No, it isn't (note </Paris instead of </Place>), and neither is your code.

var source = XElement.Load(MyFile)

Where's the semicolon?

var Query = from User in source.Descendents("User")

Descendents() doesn't exist; Descendants() does however.

where source.Element("Name").Value > "David"

Shouldn't we be referring to the User, not the source... again.

select new {Id = (int32)User.Element("Name").Value,

int32 doesn't exist... C# is case-sensitive, eh? Also, casting does not convert between strings and integers. And since when was Name an integer.

title = (string)User.Element("Attempts").Element("Date").Value}

Casting a string to a string... seems unnecessary, but where's the semicolon?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.