Cannot Deserialize xml to List<T> - c#

Im trying to deserialize this xml response of wcf web service to List using XmlSerializer but it fails with exception message :There is an error in XML document (1, 2)
xml:
<ArrayOfNote xmlns="http://schemas.datacontract.org/2004/07/NotebookService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Note>
<Author>Redouane</Author>
<Body>Test note</Body>
<CreationDate>2014-01-28T00:00:00</CreationDate>
<Id>1</Id>
<Title>Hello World</Title>
</Note>
</ArrayOfNote>
c#:
public class Note
{
public int Id { get; set; }
public string Title { get; set; }
public System.DateTime CreationDate { get; set; }
public string Author { get; set; }
public string Body { get; set; }
}
and this is the code i wrote to deserialize the received stream
private HttpClient client = new HttpClient();
private List<Note> notes = new List<Note>();
.
.
.
XmlSerializer serializer = new XmlSerializer(typeof(List<Note>));
var responseData = await response.Content.ReadAsStreamAsync();
List<Note> list = serializer.Deserialize(responseData) as List<Note>;
Please help!

Change the creation of serializer as follows and it should work.
XmlSerializer serializer = new XmlSerializer(typeof(List<Note>),
new XmlRootAttribute("ArrayOfNote") {
Namespace = "http://schemas.datacontract.org/2004/07/NotebookService"
});

Related

Casting data with a custom XML prefix to a C# model

I am trying to cast an XML document to a C# class, and for the most part, it's working fine, but in my XML I have a custom prefix, which gives me some trouble. I don't have any control over how the XML file is being generated.
<mxb:bike>Test Bike</mxb:bike>
I'm getting stuck on the mxb part since it isn't declared. My problem is that it's not declared in the XML file itself, since otherwise, it wouldn't throw the error in the first place, but I hope there is a way of solving this code side. I'm working with a .NET application, and am trying to parse an XML file to a C# model.
I'm getting the data through a post request on an API endpoint, which when I specify a model automatically converts it to that model.
My XML input is as following:
<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:gpxacx="http://www.garmin.com/xmlschemas/AccelerationExtension/v1">
<metadata>
<time>2022-09-25T12:06:47.081Z</time>
<extensions>
<mxb:bike>Test Bike</mxb:bike>
<mxb:notes>Testing</mxb:notes>
<mxb:conditions>Dry</mxb:conditions>
<mxb:track>Test Track</mxb:track>
</extensions>
</metadata>
<trk>
<trkseg>
<trkpt lat="52.914892" lon="4.776444">
<time>2022-09-25T12:06:47.081Z</time>
</trkpt>
</trkseg>
</trk>
</gpx>
My C# model looks like this:
public class GpxData
{
[XmlRoot(ElementName="extensions", Namespace="http://www.topografix.com/GPX/1/1")]
public class Extensions {
[XmlElement(ElementName="bike", Namespace="")]
public string? Bike { get; set; }
[XmlElement(ElementName="notes", Namespace="")]
public string? Notes { get; set; }
[XmlElement(ElementName="conditions", Namespace="")]
public string? Conditions { get; set; }
[XmlElement(ElementName="track", Namespace="")]
public string? Track { get; set; }
}
[XmlRoot(ElementName="metadata", Namespace="http://www.topografix.com/GPX/1/1")]
public class Metadata {
[XmlElement(ElementName="time", Namespace="http://www.topografix.com/GPX/1/1")]
public DateTime Time { get; set; }
[XmlElement(ElementName="extensions", Namespace="http://www.topografix.com/GPX/1/1")]
public Extensions Extensions { get; set; }
}
[XmlRoot(ElementName = "trkpt", Namespace = "http://www.topografix.com/GPX/1/1")]
public class Trkpt
{
[XmlElement(ElementName = "time", Namespace = "http://www.topografix.com/GPX/1/1")]
public DateTime Time { get; set; }
[XmlAttribute(AttributeName = "lat", Namespace = "")]
public double Lat { get; set; }
[XmlAttribute(AttributeName = "lon", Namespace = "")]
public double Lon { get; set; }
}
[XmlRoot(ElementName = "trkseg", Namespace = "http://www.topografix.com/GPX/1/1")]
public class Trkseg
{
[XmlElement(ElementName = "trkpt", Namespace = "http://www.topografix.com/GPX/1/1")]
public List<Trkpt> Trkpt { get; set; }
}
[XmlRoot(ElementName = "trk", Namespace = "http://www.topografix.com/GPX/1/1")]
public class Trk
{
[XmlElement(ElementName = "trkseg", Namespace = "http://www.topografix.com/GPX/1/1")]
public Trkseg Trkseg { get; set; }
}
[XmlRoot(ElementName = "gpx", Namespace = "http://www.topografix.com/GPX/1/1")]
public class Gpx
{
[XmlElement(ElementName="metadata", Namespace="http://www.topografix.com/GPX/1/1")]
public Metadata Metadata { get; set; }
[XmlElement(ElementName = "trk", Namespace = "http://www.topografix.com/GPX/1/1")]
public Trk Trk { get; set; }
[XmlAttribute(AttributeName = "creator", Namespace = "")]
public string Creator { get; set; }
}
Whenever I remove the part within the "extensions" tag, it works completely fine.
When I only remove the mxb part, and just keep the part with for example "bike" it doesn't work either.
I tried to declare the MXB prefix in the XML file itself, but since I don't have any control over the XML generation, I can't really change anything within the file, since that would only be a temporary solution, besides the fact that I don't have a schema, and as far as I know, I can't declare a prefix, without giving it a schema. Even if that would work, that wouldn't be a good solution in my case. I also tried to remove the mxb part in the XML file, and even though that solved the undeclared error issue, it would just result in the information not being cast to the model.
All the solutions I tried were related to changing something in the XML file, but that's not something I can do ;-(
I'm pretty new to XML serialzation \ deseralation, so I hope someone is able to help me! Thanks in advance.
Inspired from this answer.
You can inject a custom XmlNamespaceManager to correct missing namespace.
public class MyXmlNamespaceManager : XmlNamespaceManager
{
const string MissingNamespacePrefix = "http://missing.namespace.prefix.net/2014/";
public MyXmlNamespaceManager(XmlNameTable nameTable)
: base(nameTable)
{ }
void AddMissingNamespace(string prefix)
{
if (string.IsNullOrEmpty(prefix))
return;
string uri = MissingNamespacePrefix + prefix;
AddNamespace(prefix, uri);
}
public override bool HasNamespace(string prefix)
{
var result = base.HasNamespace(prefix);
if (!result)
AddMissingNamespace(prefix);
result = base.HasNamespace(prefix);
return result;
}
public override string LookupNamespace(string prefix)
{
var result = base.LookupNamespace(prefix);
if (result == null)
AddMissingNamespace(prefix);
result = base.LookupNamespace(prefix);
return result;
}
}
Thereby, the extension node become :
<extensions>
<mxb:bike xmlns:mxb="http://missing.namespace.prefix.net/2014/mxb">Test Bike</mxb:bike>
<mxb:notes xmlns:mxb="http://missing.namespace.prefix.net/2014/mxb">Testing</mxb:notes>
<mxb:conditions xmlns:mxb="http://missing.namespace.prefix.net/2014/mxb">Dry</mxb:conditions>
<mxb:track xmlns:mxb="http://missing.namespace.prefix.net/2014/mxb">mxb Track</mxb:track>
</extensions>
You need to adapt your model class like :
[XmlRoot(ElementName = "extensions", Namespace = "http://www.topografix.com/GPX/1/1")]
public class Extensions
{
[XmlElement(ElementName = "bike", Namespace = "http://missing.namespace.prefix.net/2014/mxb")]
public string? Bike { get; set; }
[XmlElement(ElementName = "notes", Namespace = "http://missing.namespace.prefix.net/2014/mxb")]
public string? Notes { get; set; }
[XmlElement(ElementName = "conditions", Namespace = "http://missing.namespace.prefix.net/2014/mxb")]
public string? Conditions { get; set; }
[XmlElement(ElementName = "track", Namespace = "http://missing.namespace.prefix.net/2014/mxb")]
public string? Track { get; set; }
}
Then deserialize like :
var xml = "...";
// Fix the Xml
XmlDocument xmlDoc;
using (var stream = new StringReader(xml))
{
var settings = new XmlReaderSettings();
settings.NameTable = new NameTable();
var manager = new MyXmlNamespaceManager(settings.NameTable);
XmlParserContext context = new XmlParserContext(null, manager, null, XmlSpace.Default);
using (var xmlReader = XmlReader.Create(stream, settings, context))
{
xmlDoc = new XmlDocument();
xmlDoc.Load(xmlReader);
}
}
// Deserialize
using (var stream = new MemoryStream())
{
xmlDoc.Save(stream);
stream.Seek(0, SeekOrigin.Begin);
var serializer = new XmlSerializer(typeof(GpxData.Gpx));
var result = serializer.Deserialize(stream) as GpxData.Gpx;
Console.WriteLine(result.Metadata.Extensions.Bike);
}

Cannot deserialize sub-elements to list of objects

I am having problems serializing elements of an XML to a list of objects.
This is the XML:
<result>
<stats>
<numitemsfound>1451</numitemsfound>
<startfrom>0</startfrom>
</stats>
<items>
<item>
<id>1</id>
<markedfordeletion>0</markedfordeletion>
<thumbsrc>
</thumbsrc>
<thumbsrclarge>
</thumbsrclarge>
...
<datasource>65</datasource>
<data>
<amount>100</amount>
<kj>389</kj>
<kcal>92.91</kcal>
<fat_gram>0.2</fat_gram>
<fat_sat_gram>-1</fat_sat_gram>
<kh_gram>20.03</kh_gram>
</data>
<servings>
<serving>
<serving_id>386</serving_id>
<weight_gram>150</weight_gram>
</serving>
</servings>
</item>
</result>
The classes I prepared for serialization are
[XmlType("item")]
public class Item
{
[XmlAttribute("id")]
public string id { get; set; }
[XmlAttribute("markedfordeletion")]
public string markedfordeletion { get; set; }
...
[XmlAttribute("datasource")]
public string datasource { get; set; }
[XmlElement("data")]
public Data data { get; set; }
[XmlElement("servings")]
public List<Serving> servings { get; set; }
}
}
This is how I try to serialize the xml
public void ParseSearch(string xml)
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Item>), new XmlRootAttribute("item"));
StringReader stringReader = new StringReader(xml);
var productList = (List<Item>)serializer.Deserialize(stringReader);
}
But I get the error ----> System.InvalidOperationException : <result xmlns=''> was not expected. Can you please help me solve this problem?
You have to use a serializer which serializes an instance of result, not of type List:
XmlSerializer serializer = new XmlSerializer(typeof(Result), new XmlRootAttribute("result")); //whatever `Result` actually is as type).
You can´t serialize and de-serialize just parts of a document, either the whole one or nothing at all.
So you need a root-type:
[XmlRoot("result")]
public class Result
{
public Stats Stats {get; set;}
[XmlArray("items")]
[XmlArrayItem("item")]
public List<Item> Items { get; set; }
}

Building XML request with RestSharp

I am attempting to work with a REST API using RestSharp and C#.
The documentation for the API that I am using gives a sample XML request:
<?xml version='1.0' encoding='UTF-8'?>
<messages>
<accountreference>EX0000000</accountreference>
<from>07700900654</from>
<message>
<to>07700900123</to>
<type>SMS</type>
<body>Hello Mr Sands.</body>
</message>
<message>
<to>07700900124</to>
<type>SMS</type>
<body>Hello Mr Mayo.</body>
</message>
</messages>
I am struggling to understand how to build the request in the format that they want (multiple elements called "message")
I have created these classes for RestSharp to serialize:
public class messages
{
public string accountreference { get; set; }
public string from { get; set; }
public message message { get; set; }
}
public class message
{
public string to { get; set; }
public string body { get; set; }
}
And here is my RestSharp code:
var client = new RestClient("http://api.url.com/v1.0")
{
Authenticator =
new HttpBasicAuthenticator(
UserName,
Password)
};
var request = new RestRequest("theresource", Method.POST) { RequestFormat = DataFormat.Xml };
request.AddBody(
new messages
{
accountreference = Configuration.AccountReference,
from = Configuration.From,
message =
new message { to = Configuration.Message.To, body = Configuration.Message.Body }
});
var response = client.Execute(request);
This works great when I have only 1 message element, but I don't know how to create multiple message elements without having them nested in an array, which doesn't work with the API.
By default RestSharp is using its own serializer but it also packs the DotNetSerializer so you achieve your goal by changing the serializer like this:
var request = new RestRequest("theresource", Method.POST)
{
RequestFormat = DataFormat.Xml,
XmlSerializer = new RestSharp.Serializers.DotNetXmlSerializer()
};
Then you can use a list of message objects and decorate it with XmlElement attribute:
public class messages
{
public string accountreference { get; set; }
public string from { get; set; }
[XmlElement("message")]
public List<message> messageList { get; set; }
}
public class message
{
public string to { get; set; }
public string body { get; set; }
}
Then you can change the last bit to add multiple messages:
request.AddBody(
new messages
{
accountreference = "ref",
from = "from",
messageList = new List<message>() {
new message { to = "to1", body = "body1" },
new message { to = "to2", body = "body2" }
}
});
which would produce (I got the XML by checking request.Parameters[0].Value):
<?xml version="1.0" encoding="utf-8"?>
<messages>
<accountreference>ref</accountreference>
<from>from</from>
<message>
<to>to1</to>
<body>body1</body>
</message>
<message>
<to>to2</to>
<body>body2</body>
</message>
</messages>
I guess this is the XML format you've been looking for.
Having message as list will work -
public class messages
{
public string accountreference { get; set; }
public string from { get; set; }
public List<message> message { get; set; }
}
public class message
{
public string to { get; set; }
public string body { get; set; }
}
Check the very last answer here -
How to post an array of complex objects with JSON, jQuery to ASP.NET MVC Controller?
If you face issues with list, try this -
Can RestSharp send a List<string> in a POST request?

Deserialize XML to Object Array

I'm trying to deserialize an XML file to an object array, but I'm receiving empty objects.
My question looks similar to this: How to Deserialize xml to an array of objects? but I can't seem to create a class which inherits IXmlSerializable. That said, I don't think that approach is necessary.
Am I doing something wrong?
File Object
[XmlType("file")]
public class File
{
[XmlElement("id")]
public string Id { get; set; }
[XmlElement("company_name")]
public string Company_Name { get; set; }
[XmlElement("docs")]
public HashSet<doc> Docs { get; set; }
}
Doc Object
[XmlType("doc")]
public class Doc
{
[XmlElement("valA")]
public string ValA { get; set; }
[XmlElement("valB")]
public string ValB { get; set; }
}
XML
<?xml version="1.0" encoding="UTF-8"?>
<files>
<file>
<id>12345</id>
<company_name>Apple</company_name>
<docs>
<doc>
<valA>Info</valA>
<valB>More Info</valB>
</doc>
</docs>
</file>
<file>
<id>12345</id>
<company_name>Microsoft</company_name>
<docs>
<doc>
<valA>Even More Info</valA>
<valB>Lots of it</valB>
</doc>
</docs>
</file>
</files>
Deserialization code
XmlSerializer mySerializer = new XmlSerializer(typeof(File[]), new XmlRootAttribute("files"));
using (FileStream myFileStream = new FileStream("Files.xml", FileMode.Open))
{
File[] r;
r = (File[])mySerializer.Deserialize(myFileStream);
}
You have decorated your properties with XMLAttribute but they are elements in your XML. So, change all XMLAttribute to XmlElement.
[XmlType("file")]
public class File
{
[XmlElement("id")]
public string Id { get; set; }
[XmlElement("company_name")]
public string Company_Id { get; set; }
[XmlArray("docs")]
public HashSet<Doc> Docs { get; set; }
}
[XmlType("doc")]
public class Doc
{
[XmlElement("valA")]
public string ValA { get; set; }
[XmlElement("valB")]
public string ValB { get; set; }
}
Also you XML is not well formed. I guess this is typo though -
<company_name>Apple</company_id>
<company_name>Microsoft</company_id>
Ending tag should be company_name -
<company_name>Apple</company_name>
<company_name>Microsoft</company_name>
I would use xml parser..
XDocument doc=XDocument.Load(url);
File[] r=doc.Elements("file")
.Select(f=>
new File
{
Id=f.Element("id").Value,
Company_Id=f.Element("company_name").Value,
Docs=new HashSet<Docs>(
f.Elements("docs")
.Elements("doc")
.Select(d=>
new Doc
{
ValA=d.Element("valA").Value,
ValB=d.Element("valB").Value
}))
}).ToArray();

{"<user xmlns=''> was not expected.} Deserializing Twitter XML

I'm pulling in the XML from Twitter via OAuth.
I'm doing a request to http://twitter.com/account/verify_credentials.xml, which returns the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<user>
<id>16434938</id>
<name>Lloyd Sparkes</name>
<screen_name>lloydsparkes</screen_name>
<location>Hockley, Essex, UK</location>
<description>Student</description>
<profile_image_url>http://a3.twimg.com/profile_images/351849613/twitterProfilePhoto_normal.jpg</profile_image_url>
<url>http://www.lloydsparkes.co.uk</url>
<protected>false</protected>
<followers_count>115</followers_count>
<profile_background_color>9fdaf4</profile_background_color>
<profile_text_color>000000</profile_text_color>
<profile_link_color>220f7b</profile_link_color>
<profile_sidebar_fill_color>FFF7CC</profile_sidebar_fill_color>
<profile_sidebar_border_color>F2E195</profile_sidebar_border_color>
<friends_count>87</friends_count>
<created_at>Wed Sep 24 14:26:09 +0000 2008</created_at>
<favourites_count>0</favourites_count>
<utc_offset>0</utc_offset>
<time_zone>London</time_zone>
<profile_background_image_url>http://s.twimg.com/a/1255366924/images/themes/theme12/bg.gif</profile_background_image_url>
<profile_background_tile>false</profile_background_tile>
<statuses_count>1965</statuses_count>
<notifications>false</notifications>
<geo_enabled>false</geo_enabled>
<verified>false</verified>
<following>false</following>
<status>
<created_at>Mon Oct 12 19:23:47 +0000 2009</created_at>
<id>4815268670</id>
<text>» #alexmuller your kidding? it should all be "black tie" dress code</text>
<source><a href="http://code.google.com/p/wittytwitter/" rel="nofollow">Witty</a></source>
<truncated>false</truncated>
<in_reply_to_status_id>4815131457</in_reply_to_status_id>
<in_reply_to_user_id>8645442</in_reply_to_user_id>
<favorited>false</favorited>
<in_reply_to_screen_name>alexmuller</in_reply_to_screen_name>
<geo/>
</status>
</user>
I am using the following code to deserialize:
public User VerifyCredentials()
{
string url = "http://twitter.com/account/verify_credentials.xml";
string xml = _oauth.oAuthWebRequestAsString(oAuthTwitter.Method.GET, url, null);
XmlSerializer xs = new XmlSerializer(typeof(User),"");
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xml));
return (User)xs.Deserialize(ms);
}
And I have the following for my User class:
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class User
{
[XmlElement(ElementName = "id")]
public long Id { get; set; }
[XmlElement(ElementName = "name")]
public string Name { get; set; }
[XmlElement(ElementName = "screen_name")]
public string ScreenName { get; set; }
[XmlElement(ElementName = "location")]
public string Location { get; set; }
[XmlElement(ElementName = "description")]
public string Description { get; set; }
[XmlElement(ElementName = "profile_image_url")]
public string ProfileImageUrl { get; set; }
[XmlElement(ElementName = "url")]
public string Url { get; set; }
[XmlElement(ElementName = "protected")]
public bool Protected { get; set; }
[XmlElement(ElementName = "followers_count")]
public int FollowerCount { get; set; }
[XmlElement(ElementName = "profile_background_color")]
public string ProfileBackgroundColor { get; set; }
[XmlElement(ElementName = "profile_text_color")]
public string ProfileTextColor { get; set; }
[XmlElement(ElementName = "profile_link_color")]
public string ProfileLinkColor { get; set; }
[XmlElement(ElementName = "profile_sidebar_fill_color")]
public string ProfileSidebarFillColor { get; set; }
[XmlElement(ElementName = "profile_sidebar_border_color")]
public string ProfileSidebarBorderColor { get; set; }
[XmlElement(ElementName = "friends_count")]
public int FriendsCount { get; set; }
[XmlElement(ElementName = "created_at")]
public string CreatedAt { get; set; }
[XmlElement(ElementName = "favourties_count")]
public int FavouritesCount { get; set; }
[XmlElement(ElementName = "utc_offset")]
public int UtcOffset { get; set; }
[XmlElement(ElementName = "time_zone")]
public string Timezone { get; set; }
[XmlElement(ElementName = "profile_background_image_url")]
public string ProfileBackgroundImageUrl { get; set; }
[XmlElement(ElementName = "profile_background_tile")]
public bool ProfileBackgroundTile { get; set; }
[XmlElement(ElementName = "statuese_count")]
public int StatusesCount { get; set; }
[XmlElement(ElementName = "notifications")]
public string Notifications { get; set; }
[XmlElement(ElementName = "geo_enabled")]
public bool GeoEnabled { get; set; }
[XmlElement(ElementName = "Verified")]
public bool Verified { get; set; }
[XmlElement(ElementName = "following")]
public string Following { get; set; }
[XmlElement(ElementName = "status", IsNullable=true)]
public Status CurrentStatus { get; set; }
}
But when it's deserializing the above XML the application throws the following:
$exception {"There is an error in XML document (2, 2)."} System.Exception {System.InvalidOperationException}
InnerException {"<user xmlns=''> was not expected."} System.Exception {System.InvalidOperationException}
Now I have searched around and the best solution I can find is to add blank namespaces to the serializer when you serialize the content, but i'm not serializing it so I can't.
I also have some code for receiving Statuses, which works fine.
So can someone explain to me why the error is happening? As well as a possible solution?
Either decorate your root entity with the XmlRoot attribute which will be used at compile time.
[XmlRoot(Namespace = "www.contoso.com", ElementName = "MyGroupName", DataType = "string", IsNullable=true)]
Or specify the root attribute when de serializing at runtime.
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "user";
// xRoot.Namespace = "http://www.cpandl.com";
xRoot.IsNullable = true;
XmlSerializer xs = new XmlSerializer(typeof(User),xRoot);
Even easier is just to add the following annotations to the top of your class:
[Serializable, XmlRoot("user")]
public partial class User
{
}
XmlSerializer xs = new XmlSerializer(typeof(User), new XmlRootAttribute("yourRootName"));
The error message is so vague, for me I had this code:
var streamReader = new StreamReader(response.GetResponseStream());
var xmlSerializer = new XmlSerializer(typeof(aResponse));
theResponse = (bResponse) xmlSerializer.Deserialize(streamReader);
Notice xmlSerializer is instantiated with aResponse but on deserializing I accidentally casted it to bResonse.
The simplest and best solution is just to use XMLRoot attribute in your class, in which you wish to deserialize.
Like:
[XmlRoot(ElementName = "YourPreferableNameHere")]
public class MyClass{
...
}
Also, use the following Assembly :
using System.Xml.Serialization;
In my case, my xml had multiple namespaces and attributes.
So I used this site to generate the objects - https://xmltocsharp.azurewebsites.net/
And used the below code to deserialize
XmlDocument doc = new XmlDocument();
doc.Load("PathTo.xml");
User obj;
using (TextReader textReader = new StringReader(doc.OuterXml))
{
using (XmlTextReader reader = new XmlTextReader(textReader))
{
XmlSerializer serializer = new XmlSerializer(typeof(User));
obj = (User)serializer.Deserialize(reader);
}
}
As John Saunders says, check if the class/property names matches the capital casing of your XML. If this isn't the case, the problem will also occur.
The only thing that worked in my case was by using david valentine code. Using Root Attr. in the Person class did not help.
I have this simple Xml:
<?xml version="1.0"?>
<personList>
<Person>
<FirstName>AAAA</FirstName>
<LastName>BBB</LastName>
</Person>
<Person>
<FirstName>CCC</FirstName>
<LastName>DDD</LastName>
</Person>
</personList>
C# class:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
De-Serialization C# code from a Main method:
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "personList";
xRoot.IsNullable = true;
using (StreamReader reader = new StreamReader(xmlFilePath))
{
List<Person> result = (List<Person>)(new XmlSerializer(typeof(List<Person>), xRoot)).Deserialize(reader);
int numOfPersons = result.Count;
}
My issue was that the root element actually has a xmlns="abc123"
So had to make XmlRoot("elementname",NameSpace="abc123")
Nothing worked for me for these errors EXCEPT
... was not expected,
... there is an error in XML document (1,2)
... System.FormatException Input String was not in correct format ...
Except this way
1- You need to inspect the xml response as string (the response that you are trying to de-serialize to an object)
2- Use online tools for string unescape and xml prettify/formatter
3- MAKE SURE that the C# Class (main class) you are trying to map/deserialize the xml string to HAS AN XmlRootAttribute that matches the root element of the response.
Exmaple:
My XML Response was staring like :
<ShipmentCreationResponse xmlns="http://ws.aramex.net/ShippingAPI/v1/">
<Transaction i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>
....
And the C# class definition + attributes was like :
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="ShipmentCreationResponse", WrapperNamespace="http://ws.aramex.net/ShippingAPI/v1/", IsWrapped=true)]
public partial class ShipmentCreationResponse {
.........
}
Note that the class definition does not have "XmlRootAttribute"
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://ws.aramex.net/ShippingAPI/v1/", IsNullable = false)]
And when i try to de serialize using a generic method :
public static T Deserialize<T>(string input) where T : class
{
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(T));
using (System.IO.StringReader sr = new System.IO.StringReader(input))
{
return (T)ser.Deserialize(sr);
}
}
var _Response = GeneralHelper.XMLSerializer.Deserialize<ASRv2.ShipmentCreationResponse>(xml);
I was getting the errors above
... was not expected, ... there is an error in XML document (1,2) ...
Now by just adding the "XmlRootAttribute" that fixed the issue for ever and for every other requests/responses i had a similar issue with:
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://ws.aramex.net/ShippingAPI/v1/", IsNullable = false)]
..
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://ws.aramex.net/ShippingAPI/v1/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://ws.aramex.net/ShippingAPI/v1/", IsNullable = false)]
public partial class ShipmentCreationResponse
{
........
}
My problem was one of my elements had the xmlns attribute:
<?xml version="1.0" encoding="utf-8"?>
<RETS ReplyCode="0">
<RETS-RESPONSE xmlns="blahblah">
...
</RETS-RESPONSE>
</RETS>
No matter what I tried the xmlns attribute seemed to be breaking the serializer, so I removed any trace of xmlns="..." from the xml file:
<?xml version="1.0" encoding="utf-8"?>
<RETS ReplyCode="0">
<RETS-RESPONSE>
...
</RETS-RESPONSE>
</RETS>
and voila! Everything worked.
I now parse the xml file to remove this attribute before deserializing.
Not sure why this works, maybe my case is different since the element containing the xmlns attribute is not the root element.
All above not worked for me, but this was:
Check that the name of Root element of class is exactly like the one from XML case sensitive.

Categories