Reputation: 77
I have a class which defines meteorological measurements with an API. I have created classes to store these measurements within an XML file. I have been able to write to the XML file, but am unable to read from it. I need to be able to read the data, then instantiate the Measurement Class via the constructor, and then add these instances to a List Here is the code for the Measurement constructor
public Measurement(string longit, string latitud, string cty, string pcode, DateTime dte, decimal huy, decimal pre, string windDir, int windSp) : base(longit, latitud, cty,pcode)
{
dte = date;
huy = humidity;
pre = precipitation;
windDir = windDirection;
windSp = windSpeed;
}
and here is a sample of the XML file
<Measurement>
<longitude>-76.2858726</longitude>
<latitude>36.8507689</latitude>
<city>Thetford</city>
<postcode>IP24 1ED</postcode>
<date>01/04/2011</date>
<windDirection>SE</windDirection>
<windSpeed>8</windSpeed>
<humidity>2.6</humidity>
<precipitation>0.0</precipitation>
</Measurement>
And here is the method I have written to read the file, and make an instance of the class Measurement. I receive no errors, however have not managed to create the List<>
public List<Measurement> GetList()
{
List<Measurement> measurements = new List<Measurement>();
XDocument doc = XDocument.Load(@"C:\Users\Sonya\Documents\Visual Studio 2010\Projects\WeatherAPI\WeatherAPI\measurement_store.xml");
XElement root = doc.Root;
var d = (from s in root.Descendants("Measurement")
select new Measurement
{
Longitude = s.Element("longitude").Value,
Latitude = s.Element("latitude").Value,
City = s.Element("city").Value,
Postcode = s.Element("postcode").Value,
Date = DateTime.Parse(s.Element("date").Value),
Humidity = decimal.Parse(s.Element("humidity").Value),
Precipitation = decimal.Parse(s.Element("precipitation").Value),
WindSpeed = Convert.ToInt32(s.Element("windSpeed").Value),
WindDirection = s.Element("windDirection").Value,
}).ToList();
d.ForEach(measurements.Add);
return measurements;
}//end GetList()
I've also written another method, of a slightly different format..
public List<Measurement> createXMLListMeasurements()
{
//load the xml document
XDocument doc = XDocument.Load(@"C:\Users\Sonya\Documents\Visual Studio 2010\Projects\WeatherAPI\WeatherAPI\measurement_store.xml");
//XElement root = doc.Root;
//instantiate a new list of measurements
List<Measurement> measurements = new List<Measurement>();
//get a list of measurement elements
var d = from s in doc.Descendants("Measurement")
//where
select new
{ //assign Measurement variables to data from xml doc
Longitude = (string)s.Element("longitude").Value,
Latitude = (string)s.Element("latitude").Value,
City = (string)s.Element("city").Value,
Postcode = (string)s.Element("postcode").Value,
Date = DateTime.Parse(s.Element("date").Value),
Humidity = decimal.Parse(s.Element("humidity").Value),
Precipitation = decimal.Parse(s.Element("precipitation").Value),
WindSpeed = Convert.ToInt32(s.Element("windSpeed").Value),
WindDirection = (string)s.Element("windDirection").Value,
};
foreach (var s in d)
{ //for each element found, instantiate Measurements class, and add to the measurements list.
Measurement m = new Measurement(s.Longitude, s.Latitude, s.City, s.Postcode, s.Date, s.Humidity, s.Precipitation, s.WindDirection, s.WindSpeed);
measurements.Add(m);
}
return measurements;
}
Apologies if these questions seem silly, am VERY new to LINQ and XML, so finding my way very slowly..any help much appreciated! A console application calls this method for testing and produces nothing but WeatherAPI.Measurement WeatherAPI.Measurement
Help? thanks!
Upvotes: 1
Views: 596
Reputation: 9566
Overall, your code looks fine. As Jon Skeet pointed out in his comment, you don't need to bother adding each element to a list -- you can simply return the result of the query after calling .ToList()
.
Most likely, there's either something wrong with your xml file, or you're reading it incorrectly.
If your xml file is truly just:
<Measurement>
<longitude>-76.2858726</longitude>
<latitude>36.8507689</latitude>
<city>Thetford</city>
</Measurement>
Then your code won't work, because the root of the xml file is Measurement. Therefore, calling doc.Root.Descendants("Measurement")
will give you 0 results. Instead, your xml file should have a unique root element, for example:
<root>
<Measurement>
<longitude>-76.2858726</longitude>
<latitude>36.8507689</latitude>
<city>Thetford</city>
</Measurement>
<Measurement>
<longitude>-71.2858726</longitude>
<latitude>32.1507689</latitude>
<city>Other City</city>
</Measurement>
</root>
Furthermore, you don't need to bother obtaining the Root
of the xml document. If all you want to do is find elements named Measurement
, just say doc.Descendants("Measurement")
.
Try this code with the above xml file:
void Main()
{
var measurements = GetMeasurements(@"C:\path\to\file\measurements.xml");
}
public List<Measurement> GetMeasurements(string path)
{
XDocument doc = XDocument.Load(path);
return (from s in doc.Descendants("Measurement")
select new Measurement
{
Longitude = Convert.ToDecimal(s.Element("longitude").Value),
Latitude = Convert.ToDecimal(s.Element("latitude").Value),
City = s.Element("city").Value,
}).ToList();
}
public class Measurement
{
public decimal Longitude { get; set; }
public decimal Latitude { get; set; }
public string City { get; set; }
}
When I run it in LINQPad, I get the following result:
Upvotes: 1