lloydsparkes
lloydsparkes

Reputation: 3164

{"<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>&#187; @alexmuller your kidding? it should all be &quot;black tie&quot; dress code</text>
    <source>&lt;a href=&quot;http://code.google.com/p/wittytwitter/&quot; rel=&quot;nofollow&quot;&gt;Witty&lt;/a&gt;</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?

Upvotes: 278

Views: 293012

Answers (13)

Johannes Mols
Johannes Mols

Reputation: 1041

In my case I had the [Obsolete] attribute defined on my model, which apparently causes it to be ignored by the XML deserializer...

Upvotes: 0

Jeremy Thompson
Jeremy Thompson

Reputation: 65564

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 bResponse.

Upvotes: 16

Adel Mourad
Adel Mourad

Reputation: 1547

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
{
    ........
}

Upvotes: 4

JoR
JoR

Reputation: 305

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);
            }
        }

Upvotes: 8

shdr
shdr

Reputation: 966

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.

Upvotes: 2

Khawaja Asim
Khawaja Asim

Reputation: 1387

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;

Upvotes: 8

Nick
Nick

Reputation: 3337

My issue was that the root element actually has a xmlns="abc123"

So had to make XmlRoot("elementname",NameSpace="abc123")

Upvotes: 3

user2596085
user2596085

Reputation: 39

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;
}  

Upvotes: 3

Patrick Borkowicz
Patrick Borkowicz

Reputation: 1216

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.

Upvotes: 2

david valentine
david valentine

Reputation: 4725

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);

Upvotes: 341

Ranadheer Reddy
Ranadheer Reddy

Reputation: 4324

XmlSerializer xs = new XmlSerializer(typeof(User), new XmlRootAttribute("yourRootName")); 

Upvotes: 35

Rebecca
Rebecca

Reputation: 14402

Even easier is just to add the following annotations to the top of your class:

[Serializable, XmlRoot("user")]
public partial class User
{
}

Upvotes: 161

Luuk
Luuk

Reputation: 1969

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.

Upvotes: 6

Related Questions