Reading data from XML file in C# - c#

I am attempting to read data from an XML file in C# (for Windows Phone).
I return the following XML file:
private async void GetCoords2()
{
string requestURI = "https://maps.googleapis.com/maps/api/geocode/xml?address=Donegal%20Town&key=XXX";
HttpWebRequest request = HttpWebRequest.Create(requestURI) as HttpWebRequest;
WebResponse response = await request.GetResponseAsync();
using (var reader = new StreamReader(response.GetResponseStream()))
{
responseContent = reader.ReadToEnd();
// Do anything with you content. Convert it to xml, json or anything.
ParseContent();
}
}
I am attempting to retrieve the first instance of latitude and longtitude from the XML file, which is available here: https://maps.googleapis.com/maps/api/geocode/xml?address=Donegal%20Town&key=XXX
I have followed several samples from online, and previous projects I have worked on, but none seem to be working.
How can I retrieve the first instance of lat and lon?
Thanks.
Edit: had to remove key from URL, posted screenshot of image instead.
UPDATE: The code I currently have.
void ParseContent()
{
XmlReader xmlReader = XmlReader.Create(responseContent);
List<string> aTitle = new List<string>();
// Add as many as attributes you have in your "stop" element
XmlReader reader = XmlReader.Create(responseContent);
reader.ReadToDescendant("location");
while (reader.Read())
{
reader.MoveToFirstAttribute();
reader.ReadToFollowing("lat");
string latX = reader.ReadElementContentAsString();
reader.ReadToFollowing("lng");
string lngX = reader.ReadElementContentAsString();
//reader.ReadToFollowing("Subcategory");
//string subcategory = reader.ReadElementContentAsString();
//reader.ReadToFollowing("Favourited");
//Boolean favourited = Boolean.Parse(reader.ReadElementContentAsString());
//basketxml.Add(new Pets(name, category, subcategory, description, dob, stock, price, image, id, favourited));
MessageBox.Show(latX + " / " + lngX);
}
}
FOUND ANSWER HERE:
http://www.superstarcoders.com/blogs/posts/geocoding-in-c-sharp-using-google-maps.aspx

Try something like this....
Usings...
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
Classes.... .(created from your XML using http://xmltocsharp.azurewebsites.net/)
[XmlRoot(ElementName = "address_component")]
public class Address_component
{
[XmlElement(ElementName = "long_name")]
public string Long_name { get; set; }
[XmlElement(ElementName = "short_name")]
public string Short_name { get; set; }
[XmlElement(ElementName = "type")]
public List<string> Type { get; set; }
}
[XmlRoot(ElementName = "location")]
public class Location
{
[XmlElement(ElementName = "lat")]
public string Lat { get; set; }
[XmlElement(ElementName = "lng")]
public string Lng { get; set; }
}
[XmlRoot(ElementName = "southwest")]
public class Southwest
{
[XmlElement(ElementName = "lat")]
public string Lat { get; set; }
[XmlElement(ElementName = "lng")]
public string Lng { get; set; }
}
[XmlRoot(ElementName = "northeast")]
public class Northeast
{
[XmlElement(ElementName = "lat")]
public string Lat { get; set; }
[XmlElement(ElementName = "lng")]
public string Lng { get; set; }
}
[XmlRoot(ElementName = "viewport")]
public class Viewport
{
[XmlElement(ElementName = "southwest")]
public Southwest Southwest { get; set; }
[XmlElement(ElementName = "northeast")]
public Northeast Northeast { get; set; }
}
[XmlRoot(ElementName = "geometry")]
public class Geometry
{
[XmlElement(ElementName = "location")]
public Location Location { get; set; }
[XmlElement(ElementName = "location_type")]
public string Location_type { get; set; }
[XmlElement(ElementName = "viewport")]
public Viewport Viewport { get; set; }
[XmlElement(ElementName = "bounds")]
public Bounds Bounds { get; set; }
}
[XmlRoot(ElementName = "result")]
public class Result
{
[XmlElement(ElementName = "type")]
public List<string> Type { get; set; }
[XmlElement(ElementName = "formatted_address")]
public string Formatted_address { get; set; }
[XmlElement(ElementName = "address_component")]
public List<Address_component> Address_component { get; set; }
[XmlElement(ElementName = "geometry")]
public Geometry Geometry { get; set; }
[XmlElement(ElementName = "place_id")]
public string Place_id { get; set; }
}
[XmlRoot(ElementName = "bounds")]
public class Bounds
{
[XmlElement(ElementName = "southwest")]
public Southwest Southwest { get; set; }
[XmlElement(ElementName = "northeast")]
public Northeast Northeast { get; set; }
}
[XmlRoot(ElementName = "GeocodeResponse")]
public class GeocodeResponse
{
[XmlElement(ElementName = "status")]
public string Status { get; set; }
[XmlElement(ElementName = "result")]
public List<Result> Result { get; set; }
}
Code...
try
{
string query1 = string.Format("https://maps.googleapis.com/maps/api/geocode/xml?address=Donegal%20Town&key=<Your Key>");
XmlDocument GeocodeResponse = new XmlDocument();
GeocodeResponse.Load(query1);
string XMLGeocodeResponse = GeocodeResponse.InnerXml.ToString();
byte[] BUFGeocodeResponse = ASCIIEncoding.UTF8.GetBytes(XMLGeocodeResponse);
MemoryStream ms1 = new MemoryStream(BUFGeocodeResponse);
XmlSerializer DeserializerPlaces = new XmlSerializer(typeof(GeocodeResponse), new XmlRootAttribute("GeocodeResponse"));
using (XmlReader reader = new XmlTextReader(ms1))
{
GeocodeResponse dezerializedXML = (GeocodeResponse)DeserializerPlaces.Deserialize(reader);
Location LatLng = dezerializedXML.Result[0].Geometry.Location;
}// Put a break-point here, then mouse-over LatLng and you should have you values
}
catch (System.Exception)
{
throw;
}
This will deserialize the whole thing into a single object, then you can select elements you need (as you can see with 'LatLng' above has the two coordinates you wanted to extract)...

Related

How do I deserialize an XML API response in ASP.NET?

I am working on a project that calls an API (using C# ASP.NET), and the API returns an XML document. I know how to deserialize an response in JSON, but am running into issues with deserializing an XML response. Currently I am getting the below error when attempting to deserialize the XML:
InvalidOperationException: response xmlns="" was not expected.
The error code displayed just the empty quotes in the error message. I have the code samples below, and I would greatly appreciate any constructive feedback or advice on making this better, and any advice on where I went wrong on attempting to deserialize this!
Here is the XML response from the API call (This API only returns either CML or a .csv):
<response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:noNamespaceSchemaLocation="http://www.aviationweather.gov/static/adds/schema/metar1_2.xsd">
<request_index>554967903</request_index>
<data_source name="metars"/>
<request type="retrieve"/>
<errors/>
<warnings/>
<time_taken_ms>7</time_taken_ms>
<data num_results="3">
<METAR>
<raw_text>KDEN 102353Z 15007KT 10SM FEW220 07/M08 A3038 RMK AO2 SLP285 T00721083 10133 20072 58015</raw_text>
<station_id>KDEN</station_id>
<observation_time>2022-01-10T23:53:00Z</observation_time>
<latitude>39.85</latitude>
<longitude>-104.65</longitude>
<temp_c>7.2</temp_c>
<dewpoint_c>-8.3</dewpoint_c>
<wind_dir_degrees>150</wind_dir_degrees>
<wind_speed_kt>7</wind_speed_kt>
<visibility_statute_mi>10.0</visibility_statute_mi>
<altim_in_hg>30.380905</altim_in_hg>
<sea_level_pressure_mb>1028.5</sea_level_pressure_mb>
<quality_control_flags>
<auto_station>TRUE</auto_station>
</quality_control_flags>
<sky_condition sky_cover="FEW" cloud_base_ft_agl="22000"/>
<flight_category>VFR</flight_category>
<three_hr_pressure_tendency_mb>-1.5</three_hr_pressure_tendency_mb>
<maxT_c>13.3</maxT_c>
<minT_c>7.2</minT_c>
<metar_type>METAR</metar_type>
<elevation_m>1656.0</elevation_m>
</METAR>
<METAR>
<raw_text>KSEA 102353Z 34003KT 6SM -RA BR FEW015 BKN035 OVC045 08/06 A3035 RMK AO2 SLP288 P0000 60001 T00780056 10083 20044 50003</raw_text>
<station_id>KSEA</station_id>
<observation_time>2022-01-10T23:53:00Z</observation_time>
<latitude>47.45</latitude>
<longitude>-122.32</longitude>
<temp_c>7.8</temp_c>
<dewpoint_c>5.6</dewpoint_c>
<wind_dir_degrees>340</wind_dir_degrees>
<wind_speed_kt>3</wind_speed_kt>
<visibility_statute_mi>6.0</visibility_statute_mi>
<altim_in_hg>30.351377</altim_in_hg>
<sea_level_pressure_mb>1028.8</sea_level_pressure_mb>
<quality_control_flags>
<auto_station>TRUE</auto_station>
</quality_control_flags>
<wx_string>-RA BR</wx_string>
<sky_condition sky_cover="FEW" cloud_base_ft_agl="1500"/>
<sky_condition sky_cover="BKN" cloud_base_ft_agl="3500"/>
<sky_condition sky_cover="OVC" cloud_base_ft_agl="4500"/>
<flight_category>VFR</flight_category>
<three_hr_pressure_tendency_mb>0.3</three_hr_pressure_tendency_mb>
<maxT_c>8.3</maxT_c>
<minT_c>4.4</minT_c>
<precip_in>0.005</precip_in>
<pcp6hr_in>0.01</pcp6hr_in>
<metar_type>METAR</metar_type>
<elevation_m>115.0</elevation_m>
</METAR>
<METAR>
<raw_text>PHNL 102353Z 19009KT 10SM FEW025 FEW035 SCT050 26/21 A2997 RMK AO2 SLP147 T02560206 10261 20200 58017</raw_text>
<station_id>PHNL</station_id>
<observation_time>2022-01-10T23:53:00Z</observation_time>
<latitude>21.33</latitude>
<longitude>-157.93</longitude>
<temp_c>25.6</temp_c>
<dewpoint_c>20.6</dewpoint_c>
<wind_dir_degrees>190</wind_dir_degrees>
<wind_speed_kt>9</wind_speed_kt>
<visibility_statute_mi>10.0</visibility_statute_mi>
<altim_in_hg>29.970472</altim_in_hg>
<sea_level_pressure_mb>1014.7</sea_level_pressure_mb>
<quality_control_flags>
<auto_station>TRUE</auto_station>
</quality_control_flags>
<sky_condition sky_cover="FEW" cloud_base_ft_agl="2500"/>
<sky_condition sky_cover="FEW" cloud_base_ft_agl="3500"/>
<sky_condition sky_cover="SCT" cloud_base_ft_agl="5000"/>
<flight_category>VFR</flight_category>
<three_hr_pressure_tendency_mb>-1.7</three_hr_pressure_tendency_mb>
<maxT_c>26.1</maxT_c>
<minT_c>20.0</minT_c>
<metar_type>METAR</metar_type>
<elevation_m>2.0</elevation_m>
</METAR>
</data>
</response>
This is the code to call the API:
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
client.DefaultRequestHeaders.Accept.Clear();
string baseUrl = "https://www.aviationweather.gov/adds/dataserver_current/httpparam?dataSource=metars&requestType=retrieve&format=xml&stationString=KMSP&hoursBeforeNow=2";
client.BaseAddress = new Uri(baseUrl);
HttpResponseMessage result = client.GetAsync(baseUrl).Result;
XmlSerializer serialObject = new XmlSerializer(typeof(MetarReport));
List<MetarReport> MetarCollection = new List<MetarReport>();
if (result.IsSuccessStatusCode)
{
using (Stream reader = result.Content.ReadAsStreamAsync().Result)
{
MetarReport metar = new MetarReport();
metar = (MetarReport)serialObject.Deserialize(reader);
MetarCollection.Add(metar);
}
}
// Test deserializer
foreach(var item in MetarCollection)
{
Console.WriteLine(item.rawText);
}
Console.ReadLine();
}
And this is the object I am attempting to deserialize the XML into
[XmlRoot("METAR")]
[XmlType("METAR")]
public class MetarReport
{
[XmlElement("raw_text")]
public string rawText { get; set; }
[XmlElement("station_id")]
public string stationId { get; set; }
[XmlElement("latitude")]
public double latitiude { get; set; }
[XmlElement("longitude")]
public double longitude { get; set; }
[XmlElement("temp_c")]
public double tempCelsius { get; set; }
[XmlElement("dewpoint_c")]
public double dewpoint { get; set; }
[XmlElement("wind_dir_degree")]
public int windDirection { get; set; }
[XmlElement("wind_speed_kt")]
public double windspeed { get; set; }
[XmlElement("visibility_statute_mi")]
public double visbilityMiles { get; set; }
[XmlElement("altim_in_hg")]
public double altimeter { get; set; }
//[XmlElement("sky_condition")]
//public List<SkyCondition> skyConditions {get; set;}
[XmlElement("flight_category")]
public string flightCategory { get; set; }
[XmlElement("metar_type")]
public string metarType { get; set; }
[XmlElement("elevation_m")]
public double elevationMeters { get; set; }
}
try this, it was tested in Visual Studio
HttpResponseMessage response= client.GetAsync(baseUrl).Result;
string xml;
if (response.IsSuccessStatusCode)
{
xml = response.Content.ReadAsStringAsync().Result;
}
Response result;
XmlSerializer serializer = new XmlSerializer(typeof(Response));
using (StringReader reader = new StringReader(xml))
{
result = (Response)serializer.Deserialize(reader);
}
classes
[XmlRoot(ElementName = "response")]
public class Response
{
[XmlElement(ElementName = "request_index")]
public int RequestIndex { get; set; }
[XmlElement(ElementName = "data_source")]
public DataSource DataSource { get; set; }
[XmlElement(ElementName = "request")]
public Request Request { get; set; }
[XmlElement(ElementName = "errors")]
public object Errors { get; set; }
[XmlElement(ElementName = "warnings")]
public object Warnings { get; set; }
[XmlElement(ElementName = "time_taken_ms")]
public int TimeTakenMs { get; set; }
[XmlElement(ElementName = "data")]
public Data Data { get; set; }
[XmlAttribute(AttributeName = "xsd")]
public string Xsd { get; set; }
[XmlAttribute(AttributeName = "xsi")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName = "version")]
public string Version { get; set; }
[XmlAttribute(AttributeName = "noNamespaceSchemaLocation")]
public string NoNamespaceSchemaLocation { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName = "quality_control_flags")]
public class QualityControlFlags
{
[XmlElement(ElementName = "auto_station")]
public string AutoStation { get; set; }
}
[XmlRoot(ElementName = "sky_condition")]
public class SkyCondition
{
[XmlAttribute(AttributeName = "sky_cover")]
public string SkyCover { get; set; }
[XmlAttribute(AttributeName = "cloud_base_ft_agl")]
public int CloudBaseFtAgl { get; set; }
}
[XmlRoot(ElementName = "METAR")]
public class METAR
{
[XmlElement(ElementName = "sky_condition")]
public List<SkyCondition> SkyCondition { get; set; }
[XmlElement(ElementName = "flight_category")]
public string FlightCategory { get; set; }
[XmlElement(ElementName = "three_hr_pressure_tendency_mb")]
public double ThreeHrPressureTendencyMb { get; set; }
[XmlElement(ElementName = "maxT_c")]
public decimal MaxTC { get; set; }
[XmlElement(ElementName = "minT_c")]
public decimal MinTC { get; set; }
[XmlElement(ElementName = "precip_in")]
public double PrecipIn { get; set; }
[XmlElement(ElementName = "pcp6hr_in")]
public double Pcp6hrIn { get; set; }
[XmlElement(ElementName = "metar_type")]
public string MetarType { get; set; }
[XmlElement(ElementName = "elevation_m")]
public double ElevationM { get; set; }
[XmlElement(ElementName = "raw_text")]
public string RawText { get; set; }
[XmlElement(ElementName = "station_id")]
public string StationId { get; set; }
[XmlElement(ElementName = "observation_time")]
public DateTime ObservationTime { get; set; }
[XmlElement(ElementName = "latitude")]
public double Latitude { get; set; }
[XmlElement(ElementName = "longitude")]
public double Longitude { get; set; }
[XmlElement(ElementName = "temp_c")]
public double TempC { get; set; }
[XmlElement(ElementName = "dewpoint_c")]
public double DewpointC { get; set; }
[XmlElement(ElementName = "wind_dir_degrees")]
public int WindDirDegrees { get; set; }
[XmlElement(ElementName = "wind_speed_kt")]
public int WindSpeedKt { get; set; }
[XmlElement(ElementName = "visibility_statute_mi")]
public double VisibilityStatuteMi { get; set; }
[XmlElement(ElementName = "altim_in_hg")]
public double AltimInHg { get; set; }
[XmlElement(ElementName = "sea_level_pressure_mb")]
public decimal SeaLevelPressureMb { get; set; }
[XmlElement(ElementName = "quality_control_flags")]
public QualityControlFlags QualityControlFlags { get; set; }
}
[XmlRoot(ElementName = "data")]
public class Data
{
[XmlElement(ElementName = "METAR")]
public List<METAR> METAR { get; set; }
[XmlAttribute(AttributeName = "num_results")]
public int NumResults { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName = "data_source")]
public class DataSource
{
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
}
[XmlRoot(ElementName = "request")]
public class Request
{
[XmlAttribute(AttributeName = "type")]
public string Type { get; set; }
}

Parse raw string to list of object

I am getting the List of Links in a raw string value, Is there a way to parse the raws string to a list of objects?
Eg: Raw value: <links><link id="{xxxxx-xxx-xxx}" linkid="xxxxx-xxx-xxx" text="Visit" linktype="internal" target="blank" title="Visit" querystring="" linktext="Visit" /><link id="{xxxx-xxx-xxx}" linkid="xxxx-xxx-xxx" text="Apply" linktype="internal" target="blank" title="Apply" querystring="" linktext="Apply" /></links>
To
public IEnumerable<Link> Links {get;set;}
try this
var xml=#"<links><link id='{xxxxx-xxx-xxx}' linkid='xxxxx-xxx-xxx' text='Visit' linktype='internal' target='blank' title='Visit' querystring='' linktext='Visit' /><link id='{xxxx-xxx-xxx}' linkid='xxxx-xxx-xxx' text='Apply' linktype='internal' target='blank' title='Apply' querystring='' linktext='Apply' /></links>";
......
using System.Xml.Serialization;
var serializer = new XmlSerializer(typeof(Links));
Links links;
using (StringReader reader = new StringReader(xml))
{
links = (Links)serializer.Deserialize(reader);
}
foreach (var link in links.Link)
{
Console.WriteLine($"Id: {link.Id} Text: {link.Text} ");
}
}
output
Id: {xxxxx-xxx-xxx} Text: Visit
Id: {xxxx-xxx-xxx} Text: Apply
classes
[XmlRoot(ElementName = "link")]
public class Link
{
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
[XmlAttribute(AttributeName = "linkid")]
public string Linkid { get; set; }
[XmlAttribute(AttributeName = "text")]
public string Text { get; set; }
[XmlAttribute(AttributeName = "linktype")]
public string Linktype { get; set; }
[XmlAttribute(AttributeName = "target")]
public string Target { get; set; }
[XmlAttribute(AttributeName = "title")]
public string Title { get; set; }
[XmlAttribute(AttributeName = "querystring")]
public string Querystring { get; set; }
[XmlAttribute(AttributeName = "linktext")]
public string Linktext { get; set; }
}
[XmlRoot(ElementName = "links")]
public class Links
{
[XmlElement(ElementName = "link")]
public List<Link> Link { get; set; }
}

Populate Observable collection from XML file in project (WPF)

I Have XML file in my project
Here is it
<?xml version="1.0"?>
<catalog>
<car id="1">
<model>Scoda Fabia</model>
<year>2011</year>
<producer>Folkwagen</producer>
<price>6000</price>
<owner>Bil Johnson</owner>
<tel>+5810456455456</tel>
<mileage>670000</mileage>
<registered>USA</registered>
<image>Fabia1.JPG</image>
</car>
<car id="2">
<model>Huindai Getz</model>
<year>2008</year>
<producer>Huindai</producer>
<price>5000</price>
<owner>Dimitrious Gregorakis</owner>
<tel>+5810456445456</tel>
<mileage>120000</mileage>
<registered>USA</registered>
<image>hyundai_getz2.jpg</image>
</car>
<car id="3">
<model>Huindai i108</model>
<year>2014</year>
<producer>Huindai</producer>
<price>15000</price>
<owner>Dex Dexter</owner>
<tel>+5815556445456</tel>
<mileage>30000</mileage>
<registered>Canada</registered>
<image>hyundaii108.jpg</image>
</car>
<car id="4">
<model>Aveo</model>
<year>2000</year>
<producer>Shevrole</producer>
<price>3500</price>
<owner>Ivan Ivanov</owner>
<tel>+5815556445477</tel>
<mileage>300000</mileage>
<registered>Mexico</registered>
<image>aveo.jpg</image>
</car>
</catalog>
I created a class from it, here is code for class
[XmlRoot(ElementName = "car")]
public class Car
{
[XmlElement(ElementName = "model")]
public string Model { get; set; }
[XmlElement(ElementName = "year")]
public string Year { get; set; }
[XmlElement(ElementName = "producer")]
public string Producer { get; set; }
[XmlElement(ElementName = "price")]
public string Price { get; set; }
[XmlElement(ElementName = "owner")]
public string Owner { get; set; }
[XmlElement(ElementName = "tel")]
public string Tel { get; set; }
[XmlElement(ElementName = "mileage")]
public string Mileage { get; set; }
[XmlElement(ElementName = "registered")]
public string Registered { get; set; }
[XmlElement(ElementName = "image")]
public string Image { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[XmlRoot(ElementName = "catalog")]
public class Catalog
{
[XmlElement(ElementName = "car")]
public List<Car> Car { get; set; }
}
And Created ViewModel for it, where I defined observable collection anŠ² define a method to fill it with data from XML
public class CarViewModel
{
public ObservableCollection<List<Car>> car { get; set; }
public void LoadCars()
{
Car = new ObservableCollection<List<Car>>();
var path = #"xml\CarsDatabase.xml";
using (TextReader reader = new StreamReader(path))
{
XmlSerializer serializer = new XmlSerializer(typeof(Catalog));
return (Catalog)serializer.Deserialize(reader);
}
}
}
In method LoadCars I need to fill car observable collections with data in my file, that is inside of the project.
How I can do this correctly?
Thank's for help.
UPDATE
I try to use this method
public void LoadCars()
{
Car = new ObservableCollection<List<Car>>();
var path = #"xml\CarsDatabase.xml";
using (TextReader reader = new StreamReader(path))
{
XmlSerializer serializer = new XmlSerializer(typeof(Catalog));
return (Catalog)serializer.Deserialize(reader);
}
}
But now I have error
Severity Code Description Project File Line Suppression State
Error CS0127 Since 'CarViewModel.LoadCars()' returns void, a return keyword must not be followed by an object expression DaxxTest C:\Users\nemes\Source\Repos\daxx_test\DaxxTest\DaxxTest\ViewModels\CarViewModel.cs 25 Active
Change
public ObservableCollection<List<Car>> car { get; set; }
to
public ObservableCollection<Car> car { get; set; }
And use XmlSerializer to serialize your xml information. Check bellow code for an example:
public ObservableCollection<Car> cars { get; set; }
public void LoadCars()
{
XmlSerializer serializer = new XmlSerializer(typeof(Catalog));
StreamReader reader = new StreamReader("CarsDatabase.xml");
var catalog = (Catalog)serializer.Deserialize(reader);
cars = new ObservableCollection<Car>(catalog.Car);
reader.Close();
}
[Serializable()]
public class Car
{
[XmlElement(ElementName = "model")]
public string Model { get; set; }
[XmlElement(ElementName = "year")]
public string Year { get; set; }
[XmlElement(ElementName = "producer")]
public string Producer { get; set; }
[XmlElement(ElementName = "price")]
public string Price { get; set; }
[XmlElement(ElementName = "owner")]
public string Owner { get; set; }
[XmlElement(ElementName = "tel")]
public string Tel { get; set; }
[XmlElement(ElementName = "mileage")]
public string Mileage { get; set; }
[XmlElement(ElementName = "registered")]
public string Registered { get; set; }
[XmlElement(ElementName = "image")]
public string Image { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[Serializable()]
[XmlRootAttribute("catalog", Namespace = "", IsNullable = false)]
public class Catalog
{
[XmlElement(ElementName = "car")]
public List<Car> Car { get; set; }
}

Unable to Deserialize multiple list in XML with RestSharp

I'm get this XML as a response to a rest call. The original list comes back populated fine but the list within the CollectorDate class returns null for all properties. How do I get this to Deserialize properly?
<CollectorHeardMIUs>
<CollectorDate Date="2018/07/16" CollectorId="11090_5000">
<CollectorLatitude></CollectorLatitude>
<CollectorLongitude></CollectorLongitude>
<Miu MiuId="1461860710">
<PremiseID>859869749</PremiseID>
<PremiseAccount>Unknown</PremiseAccount>
<PremiseLatitude>39.31553</PremiseLatitude>
<PremiseLongitude>-84.608627</PremiseLongitude>
</Miu>
<Miu MiuId="1478541235">
<PremiseID>859251478</PremiseID>
<PremiseAccount>Unknown</PremiseAccount>
<PremiseLatitude>39.36231</PremiseLatitude>
<PremiseLongitude>-84.54222</PremiseLongitude>
</Miu>
</CollectorDate>
<CollectorDate Date="2018/07/17" CollectorId="11090_5000">
<CollectorLatitude></CollectorLatitude>
<CollectorLongitude></CollectorLongitude>
<Miu MiuId="1461860710">
<PremiseID>859869749</PremiseID>
<PremiseAccount>Unknown</PremiseAccount>
<PremiseLatitude>39.31553</PremiseLatitude>
<PremiseLongitude>-84.608627</PremiseLongitude>
</Miu>
</CollectorDate>
</CollectorHeardMIUs>
<CollectorHeardMIUs>
<CollectorDate Date="2018/07/16" CollectorId="11090_5000">
<CollectorLatitude></CollectorLatitude>
<CollectorLongitude></CollectorLongitude>
<Miu MiuId="1461860710">
<PremiseID>859869749</PremiseID>
<PremiseAccount>Unknown</PremiseAccount>
<PremiseLatitude>39.31553</PremiseLatitude>
<PremiseLongitude>-84.608627</PremiseLongitude>
</Miu>
</CollectorDate>
<CollectorDate Date="2018/07/17" CollectorId="11090_5000">
<CollectorLatitude></CollectorLatitude>
<CollectorLongitude></CollectorLongitude>
<Miu MiuId="1461860710">
<PremiseID>859869749</PremiseID>
<PremiseAccount>Unknown</PremiseAccount>
<PremiseLatitude>39.31553</PremiseLatitude>
<PremiseLongitude>-84.608627</PremiseLongitude>
</Miu>
</CollectorDate>
</CollectorHeardMIUs>
Here are my classes:
public class CollectorDate
{
public string Date { get; set; }
public string CollectorId{ get; set; }
public decimal? CollectorLatitude { get; set; }
public decimal? CollectorLongitude { get; set; }
public List<Miu> Miu { get; set; }
}
public class Miu
{
public string MiuId { get; set; }
public string PremiseID { get; set; }
public string PremiseAccount { get; set; }
public decimal? PremiseLatitude { get; set; }
public decimal? PremiseLongitude { get; set; }
}
And my RestSharp method:
static List<CollectorDate> GetCollectorHeardMius(string token, DateTime startdt, DateTime enddt, string collectorId)
{
var client = new RestClient(ConfigurationManager.AppSettings.Get("ApiURL"));
var request = new RestRequest("collector_heard_mius");
request.AddParameter("token", token);
request.AddParameter("site_id", ConfigurationManager.AppSettings.Get("SiteId"));
request.AddParameter("start_date", startdt.ToString("yyyy/MM/dd"));
request.AddParameter("end_date", enddt.ToString("yyyy/MM/dd"));
request.AddParameter("collector_id", collectorId);
var response = client.Execute<List<CollectorDate>>(request);
return response.Data;
}
I have tried adding a class for the root element of CollectorHeardMIUs which only contains a single property of List CollectorDate but that returns a List with all empty properties.
I think the issue is with there not being a named tag for the lists of CollectorDate and Miu that is separate but I can't figure out how to handle it.
You are not able to get root Element use this code:
So I have Created a Test Application And this is Tested
So just Append it and then Deserialize it and check my model also
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//I am simply loading data From this file you can simply replace with data which are getting from rest Api
string data = File.ReadAllText("D:\\xml.txt");
string appender = "<root>" + data + "</root>";
XmlSerializer xmldata = new XmlSerializer(typeof(Root));
byte[] byteArray = Encoding.ASCII.GetBytes(data);
MemoryStream stream = new MemoryStream(byteArray);
object datafromXml = xmldata.Deserialize(stream);
}
}
[XmlRoot(ElementName = "Miu")]
public class Miu
{
[XmlElement(ElementName = "PremiseID")]
public string PremiseID { get; set; }
[XmlElement(ElementName = "PremiseAccount")]
public string PremiseAccount { get; set; }
[XmlElement(ElementName = "PremiseLatitude")]
public string PremiseLatitude { get; set; }
[XmlElement(ElementName = "PremiseLongitude")]
public string PremiseLongitude { get; set; }
[XmlAttribute(AttributeName = "MiuId")]
public string MiuId { get; set; }
}
[XmlRoot(ElementName = "CollectorDate")]
public class CollectorDate
{
[XmlElement(ElementName = "CollectorLatitude")]
public string CollectorLatitude { get; set; }
[XmlElement(ElementName = "CollectorLongitude")]
public string CollectorLongitude { get; set; }
[XmlElement(ElementName = "Miu")]
public List<Miu> Miu { get; set; }
[XmlAttribute(AttributeName = "Date")]
public string Date { get; set; }
[XmlAttribute(AttributeName = "CollectorId")]
public string CollectorId { get; set; }
}
[XmlRoot(ElementName = "CollectorHeardMIUs")]
public class CollectorHeardMIUs
{
[XmlElement(ElementName = "CollectorDate")]
public List<CollectorDate> CollectorDate { get; set; }
}
[XmlRoot(ElementName = "root")]
public class Root
{
[XmlElement(ElementName = "CollectorHeardMIUs")]
public List<CollectorHeardMIUs> CollectorHeardMIUs { get; set; }
}
}

C#: Object values null after deserializing XML

I am trying to deserialize some XML returned in an API response but all the values in my object are NULL after deserializing.
Below is the XML I am getting in the response that I am trying to deserialize.
<?xml version="1.0" encoding="utf-8"?>
<ctatt>
<tmst>20160609 11:50:03</tmst>
<errCd>0</errCd>
<errNm />
<eta>
<staId>41300</staId>
<stpId>30252</stpId>
<staNm>Loyola</staNm>
<stpDe>Service toward 95th/Dan Ryan</stpDe>
<rn>803</rn>
<rt>Red</rt>
<destSt>30089</destSt>
<destNm>95th/Dan Ryan</destNm>
<trDr>5</trDr>
<prdt>20160609 11:48:45</prdt>
<arrT>20160609 11:51:45</arrT>
<isApp>0</isApp>
<isSch>0</isSch>
<isDly>0</isDly>
<isFlt>0</isFlt>
<flags />
<lat>42.01906</lat>
<lon>-87.67289</lon>
<heading>130</heading>
</eta>
</ctatt>
Here is my class:
[Serializable, XmlRoot("ctatt")]
public class trainData
{
[XmlElement(ElementName ="tmst")]
public string timeStamp { get; set; }
[XmlElement(ElementName = "errCd")]
public byte errorCode { get; set; }
[XmlElement(ElementName = "staId")]
public ushort stationId { get; set; }
[XmlElement(ElementName = "stpId")]
public ushort stopId { get; set; }
[XmlElement(ElementName = "staNm")]
public string stationName { get; set; }
[XmlElement(ElementName = "stpDe")]
public string stopDesc { get; set; }
[XmlElement(ElementName = "rn")]
public ushort runNum { get; set; }
[XmlElement(ElementName = "rt")]
public string routeName { get; set; }
[XmlElement(ElementName = "destSt")]
public ushort destStation { get; set; }
[XmlElement(ElementName = "destNm")]
public string destName { get; set; }
[XmlElement(ElementName = "trDr")]
public byte trainDir { get; set; }
[XmlElement(ElementName = "prdt")]
public string prdTime {get; set;}
[XmlElement(ElementName = "arrT")]
public string arrTime { get; set; }
[XmlElement(ElementName = "isApp")]
public ushort isApp { get; set; }
[XmlElement(ElementName = "isSch")]
public ushort isSch { get; set; }
[XmlElement(ElementName = "isDly")]
public ushort isDly { get; set; }
[XmlElement(ElementName = "isFlt")]
public ushort isFlt { get; set; }
[XmlElement(ElementName = "flags")]
public string flags { get; set; }
[XmlElement(ElementName = "lat")]
public double lat { get; set; }
[XmlElement(ElementName = "lon")]
public double lon { get; set; }
[XmlElement(ElementName = "heading")]
public ushort heading { get; set; }
}
And here is the code I am using to deserialize:
var response = await client.GetAsync(urlParameters);
if (response.IsSuccessStatusCode)
{
var xml = await response.Content.ReadAsStringAsync();
XmlSerializer deserializer = new XmlSerializer(typeof(trainData));
using (StringReader reader = new StringReader(xml))
{
using (XmlReader xr = XmlReader.Create(reader))
{
trainData result = (trainData)deserializer.Deserialize(xr);
Console.WriteLine("Station Name: {0}\nRoute Name: {1}\nArrival Time: {2}", result.stationName, result.routeName, result.arrTime);
}
}
}
else
{
Console.WriteLine("There was an error!");
}
Any suggestions would be greatly appreciated...
The xml you provided has 2 layers ctatt and eta. Yet your model has only a single layer. Of course this is not going to work.
You need to change your model to keep the layout the same with the xml :
[Serializable, XmlRoot("ctatt")]
public class trainDataResult
{
[XmlElement(ElementName ="tmst")]
public string timeStamp { get; set; }
[XmlElement(ElementName = "errCd")]
public byte errorCode { get; set; }
// uncomment next lines to include `errNm`
//[XmlElement(ElementName = "errNm")]
//public string errorName { get; set; }
[XmlElement(ElementName = "eta")]
public TrainData eta { get; set; }
}
public class TrainData
{
[XmlElement(ElementName = "staId")]
public ushort stationId { get; set; }
[XmlElement(ElementName = "stpId")]
public ushort stopId { get; set; }
[XmlElement(ElementName = "staNm")]
public string stationName { get; set; }
[XmlElement(ElementName = "stpDe")]
public string stopDesc { get; set; }
[XmlElement(ElementName = "rn")]
public ushort runNum { get; set; }
[XmlElement(ElementName = "rt")]
public string routeName { get; set; }
[XmlElement(ElementName = "destSt")]
public ushort destStation { get; set; }
[XmlElement(ElementName = "destNm")]
public string destName { get; set; }
[XmlElement(ElementName = "trDr")]
public byte trainDir { get; set; }
[XmlElement(ElementName = "prdt")]
public string prdTime {get; set;}
[XmlElement(ElementName = "arrT")]
public string arrTime { get; set; }
[XmlElement(ElementName = "isApp")]
public ushort isApp { get; set; }
[XmlElement(ElementName = "isSch")]
public ushort isSch { get; set; }
[XmlElement(ElementName = "isDly")]
public ushort isDly { get; set; }
[XmlElement(ElementName = "isFlt")]
public ushort isFlt { get; set; }
[XmlElement(ElementName = "flags")]
public string flags { get; set; }
[XmlElement(ElementName = "lat")]
public double lat { get; set; }
[XmlElement(ElementName = "lon")]
public double lon { get; set; }
[XmlElement(ElementName = "heading")]
public ushort heading { get; set; }
}
I only know how to deserialize a list of elements from a file but maybe it helps...
List<trainData> result = new List<trainData>;
using (FileStream stream = new FileStream(Filepath,Filemode.Open)
{
XmlSerializer Serializer =new XmlSerializer(typeof(List<trainData>));
result = Serializer.Deserialize(stream);
}
If is a complexType, I believe it need as class to represent that entire element. Create a second class (for example "ETAData") to contain the elements under the . You will also need a property of that type in your trainData class and have it marked with [XmlElementAttribute] also.
EDIT: #Xiaoy312 answer is more concise and basically illustrates what I stated.

Categories