How to deserialize the following XML response in C# - c#

I received the following response from a java web service. When try to deserialize it using DataContractSerializer, I received the following error
<ns:redeemVoucherResponse xmlns:ns="http://vouchers.example.com">
<ns:return xmlns:ax236="http://util.vouchers.example.com/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ax236:RedeemStatus">
<ax236:status>fail</ax236:status>
<ax236:statusCode>4</ax236:statusCode>
<ax236:statusMessage>Error message</ax236:statusMessage>
<ax236:redeemData xsi:nil="true" />
</ns:return>
</ns:redeemVoucherResponse>
Error in line 1 position 65. Expecting element VoucherService.redeemVoucherResponse' from namespace 'http://schemas.datacontract.org/2004/07/Service.Internal.VoucherServices'.. Encountered 'Element' with name 'redeemVoucherResponse', namespace 'http://vouchers.example.com'.
Classes use for the deserialization:
public class redeemVoucherResponse {
[DataMember]
public RedeemStatus #return { get; set; }
}
public class RedeemStatus {
[DataMember]
public string status { get; set; }
[DataMember]
public byte statusCode { get; set; }
[DataMember]
public string statusMessage { get; set; }
[DataMember]
public object redeemData { get; set; }
}
Code use for the deserialization:
HttpWebResponse objWebResponse = HttpWebResponse)objWebRequest.GetResponse();
Stream objResponseStream = objWebResponse.GetResponseStream();
Type objType = typeof(redeemVoucherResponse);
DataContractSerializer objXmlSerializer = new DataContractSerializer(objType);
redeemVoucherResponse objMessage = (redeemVoucherResponse)objXmlSerializer.ReadObject(objResponseStream);

Try this ... not tested though.
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://vouchers.example.com")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://vouchers.example.com", IsNullable = false)]
public class redeemVoucherResponse
{
public redeemVoucherResponseReturn #return { get; set; }
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://vouchers.example.com")]
public class redeemVoucherResponseReturn
{
[System.Xml.Serialization.XmlElementAttribute(Namespace = "http://util.vouchers.example.com/xsd")]
public string status { get; set; }
[System.Xml.Serialization.XmlElementAttribute(Namespace = "http://util.vouchers.example.com/xsd")]
public byte statusCode { get; set; }
[System.Xml.Serialization.XmlElementAttribute(Namespace = "http://util.vouchers.example.com/xsd")]
public string statusMessage { get; set; }
[System.Xml.Serialization.XmlElementAttribute(Namespace = "http://util.vouchers.example.com/xsd", IsNullable = true)]
public object redeemData { get; set; }
}

Related

Can't deserialize xml properly

I have the following string to deserialize:
<result>
<error>
<errorcode>0</errorcode>
<errorge>წარმატებით</errorge>
<errorru>Удачно</errorru>
<erroren>successfully</erroren>
<line>89</line>
</error>
<amount>
<gel>1</gel>
</amount>
<user>01001</user>
<service>MyService</service> // here
<data>
<nickname>popcorn2</nickname>
<identification_name>identified</identification_name>
<wallet_code>5554654</wallet_code>
<NationalRate>1</NationalRate>
<RATE>1</RATE>
<GENERATED_AMOUNT>1</GENERATED_AMOUNT>
<CURRENCY>GEL</CURRENCY>
</data>
<accoutant>
<agentBenefit>0</agentBenefit>
<agentCommission>0.44</agentCommission>
<clientCommission>0</clientCommission>
</accoutant>
<service>
<min_amount>0.49</min_amount>
<max_amount>1500.00</max_amount>
<currency>GEL</currency>
</service>
<avance>-134206.1500</avance>
<operation_status>0</operation_status>
</result>
as you noticed it has two tags named "service" and they have different contents
here is the class that I've been using
[XmlRoot(ElementName = "error")]
public class ErrorInfo
{
[XmlElement(ElementName = "errorcode")]
public string Errorcode { get; set; }
[XmlElement(ElementName = "errorge")]
public string Errorge { get; set; }
[XmlElement(ElementName = "errorru")]
public string Errorru { get; set; }
[XmlElement(ElementName = "erroren")]
public string Erroren { get; set; }
[XmlElement(ElementName = "line")]
public string Line { get; set; }
}
[XmlRoot(ElementName = "amount")]
public class Amount
{
[XmlElement(ElementName = "gel")]
public string Gel { get; set; }
}
[XmlRoot(ElementName = "data")]
public class Data
{
[XmlElement(ElementName = "nickname")]
public string Nickname { get; set; }
[XmlElement(ElementName = "identification_name")]
public string Identification_name { get; set; }
[XmlElement(ElementName = "wallet_code")]
public string Wallet_code { get; set; }
[XmlElement(ElementName = "NationalRate")]
public string NationalRate { get; set; }
[XmlElement(ElementName = "RATE")]
public string RATE { get; set; }
[XmlElement(ElementName = "GENERATED_AMOUNT")]
public string GENERATED_AMOUNT { get; set; }
[XmlElement(ElementName = "CURRENCY")]
public string CURRENCY { get; set; }
}
[XmlRoot(ElementName = "accoutant")]
public class Accoutant
{
[XmlElement(ElementName = "agentBenefit")]
public string AgentBenefit { get; set; }
[XmlElement(ElementName = "agentCommission")]
public string AgentCommission { get; set; }
[XmlElement(ElementName = "clientCommission")]
public string ClientCommission { get; set; }
}
[XmlRoot(ElementName = "service")]
public class Service
{
[XmlElement(ElementName = "min_amount")]
public string Min_amount { get; set; }
[XmlElement(ElementName = "max_amount")]
public string Max_amount { get; set; }
[XmlElement(ElementName = "currency")]
public string Currency { get; set; }
}
[XmlRoot(ElementName = "result")]
public class Result
{
[XmlElement(ElementName = "error")]
public ErrorInfo Error { get; set; }
[XmlElement(ElementName = "amount")]
public Amount Amount { get; set; }
[XmlElement(ElementName = "user")]
public string User { get; set; }
[XmlElement(ElementName = "data")]
public Data Data { get; set; }
[XmlElement(ElementName = "accoutant")]
public Accoutant Accoutant { get; set; }
[XmlElement(ElementName = "service")]
public Service[] Service { get; set; }
[XmlElement(ElementName = "avance")]
public string Avance { get; set; }
[XmlElement(ElementName = "operation_status")]
public string Operation_status { get; set; }
}
I tried to handle service tags as array but it could not work. I was able to get values from the last tag , but not from the first one. both tags are neccessary so i am wondering if there is a way to get values from both tags ?
Visual Studio has this really great feature where you can put your XML in the clipboard and then do Edit -> Paste special -> Paste XML as classes.
If you do that with your XML, it generates the following class for the service tag:
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class resultService
{
private decimal min_amountField;
private decimal max_amountField;
private string currencyField;
private string[] textField;
/// <remarks/>
public decimal min_amount
{
get
{
return this.min_amountField;
}
set
{
this.min_amountField = value;
}
}
/// <remarks/>
public decimal max_amount
{
get
{
return this.max_amountField;
}
set
{
this.max_amountField = value;
}
}
/// <remarks/>
public string currency
{
get
{
return this.currencyField;
}
set
{
this.currencyField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string[] Text
{
get
{
return this.textField;
}
set
{
this.textField = value;
}
}
}
If you want to do it manually, the secret seems to be to add a field with the XmlTextAttribute attribute.
You can not have two different elements with the same name. It won't know which tag belongs where, you have to alter the name to "MyServiceName" or something similar.
Change your classes as follows:
[XmlRoot(ElementName = "result")]
public class Result
{
// no need XmlElement attribute
public ServiceComplex ServiceComplex { get; set; }
// no need XmlElement attribute
public string ServiceSimple { get; set; }
// other properties
}
// no need XmlRoot attribute
public class ServiceComplex
{
[XmlElement(ElementName = "min_amount")]
public string Min_amount { get; set; }
[XmlElement(ElementName = "max_amount")]
public string Max_amount { get; set; }
[XmlElement(ElementName = "currency")]
public string Currency { get; set; }
}
Instead of ServiceComplex and ServiceSimple, choose the names that suit you.
Subscribe XmlSerializer to UnknownElement event:
var xs = new XmlSerializer(typeof(Result));
xs.UnknownElement += Xs_UnknownElement;
private static void Xs_UnknownElement(object sender, XmlElementEventArgs e)
{
if (e.Element.Name == "service")
{
var result = (Result)e.ObjectBeingDeserialized;
if (e.Element.ChildNodes.Count == 1)
{
result.ServiceSimple = e.Element.InnerText;
}
else
{
result.ServiceComplex = new ServiceComplex
{
Min_amount = e.Element.SelectSingleNode("min_amount").InnerText,
Max_amount = e.Element.SelectSingleNode("max_amount").InnerText,
Currency = e.Element.SelectSingleNode("currency").InnerText
};
}
}
}
In the event handler, we manually populate the properties of our class from xml.

Parsing XML in C# from xml REST POST webResponse

I'm trying to parse an XML response from a REST endpoint. I am using a POST request (if that's relevant). I can't get the document to parse correctly. I've researched this all over stack overflow, and none seem to be applicable to my response. How can i parse my XML? I've tried all of the below:
Using XDocument:
Stream postData = resp.GetResponseStream();
StreamReader reader = new StreamReader(postData, Encoding.UTF8);
string result = reader.ReadToEnd();
var document = XDocument.Parse(result);
XNamespace ns = XNamespace.Get("http://www.w3.org/2005/Atom");
var items = document.Descendants("NameFirst")
.ToDictionary(i => (string)i.Attribute("Key"),
i => (string)i.Attribute("Value"));
Using nested for each with XElements:
Stream postData = resp.GetResponseStream();
StreamReader reader = new StreamReader(postData, Encoding.UTF8);
string result = reader.ReadToEnd();
XDocument document = XDocument.Parse(result);
XNamespace ns = XNamespace.Get("http://www.w3.org/2005/Atom");
string list = "";
foreach (XElement level1 in document.Elements("feed"))
{
foreach (XElement level2 in level1.Elements("entry"))
{
foreach (XElement level3 in level2.Elements("content"))
{
foreach (XElement entry in level3.Elements("Entry"))
{
list += entry.Attribute("NameFirst").Value;
list += entry.Attribute("NameLast").Value;
}
}
}
}
Using a concatenation of Descendant methods:
Stream postData = resp.GetResponseStream();
StreamReader reader = new StreamReader(postData, Encoding.UTF8);
string result = reader.ReadToEnd();
var document = XDocument.Parse(result);
XNamespace ns = XNamespace.Get("http://www.w3.org/2005/Atom");
var listOfFields = document.Descendants(ns + "feed").Descendants(ns + "entry").Descendants(ns + "content").Descendants(ns + "entry").Select(x => x.Elements().First().Value).ToList();
ResultLabel.Text = "";
foreach(String item in listOfFields){
ResultLabel.Text += item;
}
Using multiple Element methods:
Stream postData = resp.GetResponseStream();
StreamReader reader = new StreamReader(postData, Encoding.UTF8);
string result = reader.ReadToEnd();
var document = XDocument.Parse(result);
XNamespace ns = XNamespace.Get("http://www.w3.org/2005/Atom");
var listOfFields = document.Descendants(ns + "feed").Descendants(ns + "entry").Descendants(ns + "content").Descendants(ns + "entry").Select(x => x.Elements().First().Value).ToList();
var entry_ = document.Root.Element("entry");
var content = entry_.Element("content");
var entry = content.Element("Entry");
var fname = entry.Element("NameFirst").Value;
var lname = entry.Element("NameLast").Value;
ResultLabel.Text = string.Join(",", lname, fname);
My XML response:
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text">Search Results</title>
<id>https://myendpoint.com/Rest/services/select/Entry</id>
<updated>2015-10-07T09:51:32Z</updated>
<link rel="self" type="application/atom+xml" href="https://myendpoint.com/Rest/services/select/Entry" />
<entry>
<id>https://myendpoint.com/services/select/Entry/26032</id>
<title type="text">Smith, John</title>
<published>2013-10-08T10:14:20Z</published>
<updated>2015-10-02T12:14:18Z</updated>
<contributor><name>WebUser</name></contributor>
<content type="xhtml">
<Entry>
<EntryID>26032</EntryID>
<CategoryID>0</CategoryID>
<EventID>0</EventID>
<GroupID>0</GroupID>
<ContactID>0</ContactID>
<AddressTypeID>0</AddressTypeID>
<PinNumber>0000</PinNumber>
<Password></Password>
<PortalEmail></PortalEmail>
<NameLast>Smith</NameLast>
<NameFirst>John</NameFirst>
<NameTitle></NameTitle>
<NamePreferred>Mike</NamePreferred>
<NameWeb>smith</NameWeb>
<NameOther></NameOther>
<NameInitials></NameInitials>
<NameSharer></NameSharer>
<GenderEnum>Female</GenderEnum>
<Birth_GenderEnum>Male</Birth_GenderEnum>
<DirectoryFlagPrivacy>false</DirectoryFlagPrivacy>
<Position></Position>
<ID1>123456</ID1>
<ID2>smith</ID2>
<ID3></ID3>
<ID4>0</ID4>
<ID5>0</ID5>
<PhoneProcessToAccount>true</PhoneProcessToAccount>
<PhoneChargeTypeID>0</PhoneChargeTypeID>
<PhoneDisableValue>0</PhoneDisableValue>
<PhoneRestrictValue>0</PhoneRestrictValue>
<PhoneControlEnum>Default</PhoneControlEnum>
<TaxExemptionEnum>None</TaxExemptionEnum>
<Testing>true</Testing>
<timestamp>000007975236</timestamp>
</Entry>
</content>
</entry>
</feed>
You can deserialize the XML into easily accessible objects. Here's how to do it:
Create the objects that will hold your deserialized data:
You can easily do it by copying the XML you're getting from your REST endpoint then in Visual Studio go to Edit -> Paste Special -> Paste XML as classes
Once your classes are created you will get something like this:
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.w3.org/2005/Atom")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.w3.org/2005/Atom", IsNullable = false)]
public partial class feed
{
public feedTitle title { get; set; }
public string id { get; set; }
public System.DateTime updated { get; set; }
public feedLink link { get; set; }
public feedEntry entry { get; set; }
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.w3.org/2005/Atom")]
public partial class feedTitle
{
[System.Xml.Serialization.XmlAttributeAttribute()]
public string type { get; set; }
[System.Xml.Serialization.XmlTextAttribute()]
public string Value { get; set; }
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.w3.org/2005/Atom")]
public partial class feedLink
{
[System.Xml.Serialization.XmlAttributeAttribute()]
public string rel { get; set; }
[System.Xml.Serialization.XmlAttributeAttribute()]
public string type { get; set; }
[System.Xml.Serialization.XmlAttributeAttribute()]
public string href { get; set; }
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.w3.org/2005/Atom")]
public partial class feedEntry
{
public string id { get; set; }
public feedEntryTitle title { get; set; }
public System.DateTime published { get; set; }
public System.DateTime updated { get; set; }
public feedEntryContributor contributor { get; set; }
public feedEntryContent content { get; set; }
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.w3.org/2005/Atom")]
public partial class feedEntryTitle
{
[System.Xml.Serialization.XmlAttributeAttribute()]
public string type { get; set; }
[System.Xml.Serialization.XmlTextAttribute()]
public string Value { get; set; }
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.w3.org/2005/Atom")]
public partial class feedEntryContributor
{
public string name { get; set; }
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.w3.org/2005/Atom")]
public partial class feedEntryContent
{
public feedEntryContentEntry Entry { get; set; }
[System.Xml.Serialization.XmlAttributeAttribute()]
public string type { get; set; }
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.w3.org/2005/Atom")]
public partial class feedEntryContentEntry
{
public ushort EntryID { get; set; }
public byte CategoryID { get; set; }
public byte EventID { get; set; }
public byte GroupID { get; set; }
public byte ContactID { get; set; }
public byte AddressTypeID { get; set; }
public byte PinNumber { get; set; }
public object Password { get; set; }
public object PortalEmail { get; set; }
public string NameLast { get; set; }
public string NameFirst { get; set; }
public object NameTitle { get; set; }
public string NamePreferred { get; set; }
public string NameWeb { get; set; }
public object NameOther { get; set; }
public object NameInitials { get; set; }
public object NameSharer { get; set; }
public string GenderEnum { get; set; }
public string Birth_GenderEnum { get; set; }
public bool DirectoryFlagPrivacy { get; set; }
public object Position { get; set; }
public uint ID1 { get; set; }
public string ID2 { get; set; }
public object ID3 { get; set; }
public byte ID4 { get; set; }
public byte ID5 { get; set; }
public bool PhoneProcessToAccount { get; set; }
public byte PhoneChargeTypeID { get; set; }
public byte PhoneDisableValue { get; set; }
public byte PhoneRestrictValue { get; set; }
public string PhoneControlEnum { get; set; }
public string TaxExemptionEnum { get; set; }
public bool Testing { get; set; }
public uint timestamp { get; set; }
}
Then you can deserialize the XML into a feed object like the following:
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("Your XML string here")))
{
XmlSerializer serializer = new XmlSerializer(typeof(feed));
feed feedObject = (feed)serializer.Deserialize(ms);
// Then you can access the xml content like you do with any object.
Console.WriteLine(feedObject.title.Value);
}
Live demo

deserialize xml in complex object

I can't understand why object is null:
WebClient browse = new WebClient();
StreamReader res = new StreamReader(browse.OpenRead("http://ws.audioscrobbler.com/2.0/?method=track.getinfo&api_key=b25b959554ed76058ac220b7b2e0a026&artist=cher&track=believe"));
string result = res.ReadToEnd();
XmlDocument xmltrackinfo = new XmlDocument();
xmltrackinfo.InnerXml = result;
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "lfm";
xRoot.IsNullable = true;
XmlSerializer xs = new XmlSerializer(typeof(fm), xRoot);
fm rez = (fm) xs.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(result)));
Object Model:
[Serializable()]
[XmlRoot(ElementName = "lfm", IsNullable = true)]
public class fm
{
[XmlElement("lfm")]
public Track lfm { get; set; }
}
[Serializable()]
[XmlRoot(ElementName = "artist", IsNullable = true)]
public class artist
{
public string name { get; set; }
public string mbid { get; set; }
public string url { get; set; }
}
[Serializable()]
[XmlRoot(ElementName = "album", IsNullable = true)]
public class album
{
public string artist { get; set; }
public string title { get; set; }
public string mbid { get; set; }
public string url { get; set; }
public List<string> image { get; set; }
}
[Serializable()]
[XmlRoot(ElementName = "tag", IsNullable = true)]
public class tag
{
public string name { get; set; }
public string url { get; set; }
}
[Serializable()]
[XmlRoot(ElementName = "wiki", IsNullable = true)]
public class wiki
{
public string summary { get; set; }
public string content { get; set; }
}
[Serializable()]
[XmlRoot(ElementName = "track", IsNullable = true)]
public class Track
{
public string id { get; set; }
public string name { get; set; }
public string mbid { get; set; }
public string url { get; set; }
public string duration { get; set; }
public string streamable { get; set; }
public string listeners { get; set; }
public string playcount { get; set; }
public artist artist { get; set; }
public album album { get; set; }
public List<tag> toptags { get; set; }
public wiki wiki { get; set; }
}
and XML:
http://ws.audioscrobbler.com/2.0/?method=track.getinfo&api_key=b25b959554ed76058ac220b7b2e0a026&artist=cher&track=believe
so what should I do?
Try renaming your fm class to lfm.
public class lfm
{
public Track track { get; set; }
}
and then you could also get rid of the xRoot variable:
XmlSerializer xs = new XmlSerializer(typeof(lfm));
lfm rez = (lfm) xs.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(result)));
Also you don't need the [Serializable] attribute. This is used for binary serialization and is completely ignored by the XmlSerializer class.
The lfm property of the fm class must have track as its XmlElement:
[Serializable()]
[XmlRoot(ElementName = "lfm", IsNullable = true)]
public class fm
{
[XmlElement("track")]
public Track lfm { get; set; }
}

.NET Xml deserialization, issue/error with xsi:type attribute

VS2008, .NET Framework 3.5
We're utilizing the WebEx Xml API. Here's a sample Xml response from their web service that I'm trying to deserialize into .NET classes.
<?xml version="1.0" encoding="UTF-8"?>
<serv:message xmlns:serv="http://www.webex.com/schemas/2002/06/service" xmlns:com="http://www.webex.com/schemas/2002/06/common"
xmlns:event="http://www.webex.com/schemas/2002/06/service/event"><serv:header><serv:response><serv:result>SUCCESS</serv:result><serv:gsbStatus>PRIMARY</s
erv:gsbStatus></serv:response></serv:header>
<serv:body>
<serv:bodyContent xsi:type="event:lstsummaryEventResponse" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<event:matchingRecords>
<serv:total>2</serv:total>
<serv:returned>2</serv:returned>
<serv:startFrom>1</serv:startFrom>
</event:matchingRecords>
<event:event>
<event:sessionKey>999999</event:sessionKey>
<event:sessionName>Test Event 1</event:sessionName>
<event:sessionType>129</event:sessionType>
<event:hostWebExID>SomeName</event:hostWebExID>
<event:startDate>03/28/2012 14:30:00</event:startDate>
<event:endDate>03/28/2012 14:45:00</event:endDate>
<event:timeZoneID>11</event:timeZoneID>
<event:duration>15</event:duration>
<event:description></event:description>
<event:status>NOT_INPROGRESS</event:status>
<event:panelists></event:panelists>
<event:listStatus>PUBLIC</event:listStatus>
</event:event>
</serv:bodyContent>
</serv:body>
</serv:message>
Here's the class that we're deserializing into:
using System;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Collections.Generic;
namespace Masonite.MTier.WebEx
{
[Serializable()]
[XmlRoot("message", Namespace = "http://www.webex.com/schemas/2002/06/service")]
public class lstsummaryEventResponsexx
{
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces();
public lstsummaryEventResponsexx()
{
xmlns.Add("serv", "http://www.webex.com/schemas/2002/06/service");
xmlns.Add("com", "http://www.webex.com/schemas/2002/06/common");
xmlns.Add("event", "http://www.webex.com/schemas/2002/06/service/event");
}
[XmlElement(ElementName = "header")]
public Header header { get; set; }
[XmlElement(ElementName = "body")]
public Body body { get; set; }
[Serializable()]
[XmlRoot("header")]
public class Header
{
[XmlElement(ElementName = "response")]
public Response response { get; set; }
}
[Serializable()]
[XmlRoot("body")]
[XmlInclude(typeof(lstsummaryEventResponse))]
public class Body
{
[XmlElement(ElementName = "bodyContent", Form = XmlSchemaForm.Qualified)]
public BodyContent bodyContent { get; set; }
}
[Serializable()]
public class lstsummaryEventResponse
{
}
[Serializable()]
[XmlRoot("response")]
public class Response
{
[XmlElement(ElementName = "result")]
public string result { get; set; }
[XmlElement(ElementName = "reason")]
public string reason { get; set; }
[XmlElement(ElementName = "gsbStatus")]
public string gsbStatus { get; set; }
[XmlElement(ElementName = "exceptionID")]
public string exceptionID { get; set; }
}
[Serializable()]
[XmlRoot("bodyContent")]
public class BodyContent
{
[XmlElement(ElementName = "matchingRecords", Namespace = "http://www.webex.com/schemas/2002/06/service/event")]
public MatchingRecords matchingRecords { get; set; }
[XmlElement(ElementName = "event", Namespace = "http://www.webex.com/schemas/2002/06/service/event")]
public List<EventSummary> events { get; set; }
}
[Serializable()]
[XmlRoot("matchingRecords")]
public class MatchingRecords
{
[XmlElement(ElementName = "total", Namespace = "http://www.webex.com/schemas/2002/06/service")]
public int total { get; set; }
[XmlElement(ElementName = "returned", Namespace = "http://www.webex.com/schemas/2002/06/service")]
public int returned { get; set; }
[XmlElement(ElementName = "startFrom", Namespace = "http://www.webex.com/schemas/2002/06/service")]
public int startFrom { get; set; }
}
[Serializable()]
[XmlRoot("event")]
public class EventSummary
{
[XmlElement(ElementName = "sessionKey")]
public long sessionKey { get; set; }
[XmlElement(ElementName = "sessionName")]
public string sessionName { get; set; }
[XmlElement(ElementName = "sessionType")]
public int sessionType { get; set; }
[XmlElement(ElementName = "hostWebExID")]
public string hostWebExID { get; set; }
[XmlElement(ElementName = "startDate")]
public string startDate { get; set; }
[XmlElement(ElementName = "endDate")]
public string endDate { get; set; }
[XmlElement(ElementName = "timeZoneID")]
public int timeZoneID { get; set; }
[XmlElement(ElementName = "duration")]
public int duration { get; set; }
[XmlElement(ElementName = "description")]
public string description { get; set; }
[XmlElement(ElementName = "status")]
public string status { get; set; }
[XmlElement(ElementName = "panelists")]
public string panelists { get; set; }
[XmlElement(ElementName = "listStatus")]
public listingType listStatus { get; set; }
}
}
}
The error I'm receiving:
The specified type was not recognized: name='lstsummaryEventResponse', namespace='http://www.webex.com/schemas/2002/06/service/event', at <bodyContent xmlns='http://www.webex.com/schemas/2002/06/service'>
I'm not sure how to provide the type lstsummaryEventResponse for the Deserialize method. I added another serializable class to my class above using that name, but get the same error. Any thoughts?
BodyContent can have the type event:lstsummaryEventResponse - so you have to declare the corresponding class, and then decorate the declaration of BodyContent as follows:
[Serializable()]
[XmlRoot("bodyContent")]
[XmlInclude("lstsummaryEventResponse")]
public class BodyContent {
}
Having said that, creating C# class with a serialization corresponding to some arbitrary XML is pretty tricky, I am not sure it is right approach

XmlSerializer Deserialize returns empty array

I'm trying to deserialize the following XML (excerpt):
<NSArray>
<Song id="23507" type="Song">
<title>Waking The Demon</title>
<artist id="17" type="Artist">
<nameWithoutThePrefix>Bullet For My Valentine</nameWithoutThePrefix>
<useThePrefix>false</useThePrefix>
<name>Bullet For My Valentine</name>
</artist>
</Song>
<Song id="3663" type="Song">
<title>Hand Of Blood</title>
<artist id="17" type="Artist"/>
</Song>
<Song id="59226" type="Song">
<title>Your Betrayal</title>
<artist id="17" type="Artist"/>
</Song>
</NSArray>
with the following classes:
[GeneratedCode("xsd", "4.0.30319.1")]
[DebuggerStepThrough]
[XmlType(AnonymousType = true)]
[XmlRoot(ElementName = "NSArray", Namespace = "", IsNullable = false)]
public class SearchResult
{
[XmlElement("Song", Form = XmlSchemaForm.Unqualified)]
public Song[] Items { get; set; }
}
[GeneratedCode("xsd", "4.0.30319.1")]
[DebuggerStepThrough]
[XmlType(AnonymousType = true)]
[XmlRoot(Namespace = "", IsNullable = false)]
public class Song
{
[XmlElement(Form = XmlSchemaForm.Unqualified)]
public string Title { get; set; }
[XmlElement("artist", Form = XmlSchemaForm.Unqualified)]
public Artist Artist { get; set; }
[XmlAttribute]
public string Type { get; set; }
[XmlAttribute]
public string Id { get; set; }
}
[GeneratedCode("xsd", "4.0.30319.1")]
[DebuggerStepThrough]
[XmlType(AnonymousType = true)]
public class Artist
{
[XmlElement(Form = XmlSchemaForm.Unqualified)]
public string NameWithoutThePrefix { get; set; }
[XmlElement(Form = XmlSchemaForm.Unqualified)]
public string UseThePrefix { get; set; }
[XmlElement(Form = XmlSchemaForm.Unqualified)]
public string Name { get; set; }
[XmlAttribute]
public string Type { get; set; }
[XmlAttribute]
public string Id { get; set; }
}
and the following code:
var request = WebRequest.Create(string.Format("http://myurl.com");
request.BeginGetResponse(GetEventResponseCallback, request);
private void GetEventResponseCallback(IAsyncResult result)
{
var request = (HttpWebRequest)result.AsyncState;
var response = request.EndGetResponse(result);
if (response.GetResponseStream() == null) return;
using (var stream = response.GetResponseStream())
{
_xmlReader = XmlReader.Create(stream);
var songs = _xmlSerializer.Deserialize(_xmlReader) as SearchResult;
}
}
However, on var songs = _xmlSerializer.Deserialize(_xmlReader) as SearchResult;, the Deserialization executes successfully, but the songs variable does not contain any data. If I inspect with the debugger, it returns Could not evaluate expression for all the values in the array.
Any hints? Thanks.
Your SearchResult class needs some fixing. You're really close, the code is only missing a few element names and the serializable attributes.
Here's a class that works:
[GeneratedCode("xsd", "4.0.30319.1")]
[DebuggerStepThrough]
[XmlType(AnonymousType = true)]
[XmlRoot(ElementName = "NSArray", Namespace = "", IsNullable = false)]
[Serializable]
public class SearchResult
{
[XmlElement("Song", Form = XmlSchemaForm.Unqualified)]
public Song[] Items { get; set; }
}
[GeneratedCode("xsd", "4.0.30319.1")]
[DebuggerStepThrough]
[XmlType(AnonymousType = true)]
[XmlRoot(ElementName="Song", Namespace = "", IsNullable = false)]
[Serializable]
public class Song
{
[XmlElement("title", Form = XmlSchemaForm.Unqualified)]
public string Title { get; set; }
[XmlElement("artist", Form = XmlSchemaForm.Unqualified)]
public Artist Artist { get; set; }
[XmlAttribute("type")]
public string Type { get; set; }
[XmlAttribute("id")]
public string Id { get; set; }
}
[GeneratedCode("xsd", "4.0.30319.1")]
[DebuggerStepThrough]
[XmlType(AnonymousType = true)]
[Serializable]
public class Artist
{
[XmlElement("nameWithoutThePrefix", Form = XmlSchemaForm.Unqualified)]
public string NameWithoutThePrefix { get; set; }
[XmlElement("useThePrefix", Form = XmlSchemaForm.Unqualified)]
public string UseThePrefix { get; set; }
[XmlElement("name", Form = XmlSchemaForm.Unqualified)]
public string Name { get; set; }
[XmlAttribute("type")]
public string Type { get; set; }
[XmlAttribute("id")]
public string Id { get; set; }
}
I have a class that I am serializing and deserializing. Compared to the attributes you are using... you have a lot that I don't have (on the class), but one that you are missing is [Serializable]
Mine looks like this:
[Serializable]
public class Settings
{
[XmlElement]
public int Version { get; set; }
[XmlElement]
public string Name { get; set; }
// more settings
}
So start with something simple like this, that works, then add in each new tag one at a time, and you will quickly find which one is causing it to break.
Since you are having trouble deserializing, here is the code I am using. In another class, I have:
public string FilePath { get; set; }
public Settings LoadSettings()
{
XmlSerializer serializer = new XmlSerializer(typeof(Settings));
Settings settings = null;
using(TextReader reader = new StreamReader(this.FilePath))
{
settings = (Settings)serializer.Deserialize(reader);
}
return settings;
}

Categories