I'm currently learning how to handle XML in C#, and I'm trying to parse and create an object from this url: https://api.met.no/weatherapi/locationforecast/1.9/?lat=60.10&lon=9.58
Function call
var data = GetXmlData(url);
LocationForecast forecastNextHour = data.First();
Parsing
private IEnumerable<LocationForecast> GetXmlData(string url)
{
// Create new XDocument
XDocument xdoc = XDocument.Load(url);
// Get first element in XML with forecast datatype (next hour)
XElement selectedElement = xdoc.Descendants().First(x => (string)x.Attribute("datatype") == "forecast");
var locationData = from x in selectedElement.Descendants()
let temperature = x.Element("temperature")
where temperature != null
let windDirection = x.Element("windDirection")
where windDirection != null
let windSpeed = x.Element("windSpeed")
where windSpeed != null
let windGust = x.Element("windGust")
where windGust != null
let humidity = x.Element("humidity")
where humidity != null
let pressure = x.Element("pressure")
where pressure != null
let cloudiness = x.Element("cloudiness")
where cloudiness != null
let fog = x.Element("fog")
where fog != null
let lowClouds = x.Element("lowClouds")
where lowClouds != null
let mediumClouds = x.Element("mediumClouds")
where mediumClouds != null
let highClouds = x.Element("highClouds")
where highClouds != null
let dewpointTemperature = x.Element("dewpointTemperature")
where dewpointTemperature != null
// Get data from selected portion of XML
select new LocationForecast()
{
Temperature = (double)temperature.Attribute("value"),
WindDirection = (double)windDirection.Attribute("deg"),
WindSpeed = (double)windSpeed.Attribute("mps"),
WindGust = (double)windGust.Attribute("mps"),
Humidity = (double)humidity.Attribute("value"),
Pressure = (double)pressure.Attribute("value"),
Cloudiness = (double)cloudiness.Attribute("percent"),
Fog = (double)fog.Attribute("percent"),
LowClouds = (double)lowClouds.Attribute("percent"),
MediumClouds = (double)mediumClouds.Attribute("percent"),
HighClouds = (double)highClouds.Attribute("percent"),
DewpointTemperature = (double)dewpointTemperature.Attribute("value"),
};
return locationData;
}
The code works but it seems a bit inefficient, as I return an IEnumerable where I have to use .First() on the returned object to get the actual object with properties. With this code I'm also unable to get hold of the other time-elements where the from="" and to="" attributes are the same (forecast for that hour) and I would like to get hold of the hourly forecasts for at least the three next hours.
I've tried using xsd.exe to create a class from the schema, but that made no sense so currently I'm sticking with my LocationForecast class.
Is there a more efficient way of doing this parsing, and to get hold of the next hourly forecasts?