{"<user xmlns = ''> не ожидалось.} Deserializing Twitter XML

Я извлекаю XML из Twitter через OAuth.

Я делаю запрос к http://twitter.com/account/verify_credentials.xml, который возвращает следующий 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>

Я использую следующий код для десериализации:

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

И у меня есть следующее для моего класса User:

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

}

Но при десериализации вышеуказанного XML приложение выдает следующее:

  • $ exception {"Ошибка в XML-документе (2, 2)."} System.Exception {System.InvalidOperationException}

  • InnerException {"<user xmlns = ''> не ожидалось."} System.Exception {System.InvalidOperationException}

Теперь я искал вокруг, и лучшее решение, которое я могу найти, - это добавить пустые пространства имен в сериализатор, когда вы сериализуете контент, но я не сериализую его, поэтому я не могу.

У меня также есть код для получения статусов, который отлично работает.

Так может кто-нибудь объяснить мне, почему происходит ошибка? Как и возможное решение?

Заранее спасибо.

Ответ 1

Либо украсьте свой корневой объект атрибутом XmlRoot, который будет использоваться во время компиляции.

[XmlRoot(Namespace = "www.contoso.com", ElementName = "MyGroupName", DataType = "string", IsNullable=true)]

Или укажите атрибут root при сериализации во время выполнения.

XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "user";
// xRoot.Namespace = "http://www.cpandl.com";
xRoot.IsNullable = true;

XmlSerializer xs = new XmlSerializer(typeof(User),xRoot);

Ответ 2

Еще проще просто добавить следующие аннотации в начало вашего класса:

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

Ответ 3

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

Ответ 4

Сообщение об ошибке настолько неопределенно, для меня у меня был этот код:

var streamReader = new StreamReader(response.GetResponseStream());
var xmlSerializer = new XmlSerializer(typeof(aResponse));
theResponse = (bResponse) xmlSerializer.Deserialize(streamReader);

Обратите внимание, что xmlSerializer создается с помощью aResponse, но при десериализации я случайно использовал его для bResonse.

Ответ 5

Как говорит Джон Сондерс, проверьте, соответствуют ли имена классов/свойств основному корпусу вашего XML. Если это не так, проблема также возникнет.

Ответ 6

Самое простое и лучшее решение - просто использовать атрибут XMLRoot в своем классе, в котором вы хотите десериализовать.

Подобно:

[XmlRoot(ElementName = "YourPreferableNameHere")]
public class MyClass{
...
}

Кроме того, используйте следующую сборку:

using System.Xml.Serialization;

Ответ 7

Моя проблема заключалась в том, что один из моих элементов имел атрибут xmlns:

<?xml version="1.0" encoding="utf-8"?>
<RETS ReplyCode="0">
    <RETS-RESPONSE xmlns="blahblah">
        ...
    </RETS-RESPONSE>
</RETS>

Независимо от того, что я пробовал, атрибут xmlns, казалось, разбивал сериализатор, поэтому я удалил любой след xmlns = "..." из файла xml:

<?xml version="1.0" encoding="utf-8"?>
<RETS ReplyCode="0">
    <RETS-RESPONSE>
        ...
    </RETS-RESPONSE>
</RETS>

и вуаля! Все работало.

Теперь я разбираю XML файл, чтобы удалить этот атрибут перед десериализацией. Не знаю, почему это работает, может быть, мой случай отличается от того, что элемент, содержащий атрибут xmlns, не является корневым элементом.

Ответ 8

Единственное, что сработало в моем случае, - это использовать код valdine от Дэвида. Использование Root Attr. в классе Person не помогло.

У меня есть этот простой Xml:

<?xml version="1.0"?>
<personList>
 <Person>
  <FirstName>AAAA</FirstName>
  <LastName>BBB</LastName>
 </Person>
 <Person>
  <FirstName>CCC</FirstName>
  <LastName>DDD</LastName>
 </Person>
</personList>

Класс С#:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Код де-сериализации С# из основного метода:

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

Ответ 9

Моя проблема заключалась в том, что корневой элемент на самом деле имеет xmlns = "abc123"

Так было нужно сделать XmlRoot ( "elementname", NameSpace = "abc123" )

Ответ 10

Все выше не работало для меня, но это было: Убедитесь, что имя элемента Root класса точно похоже на имя из чувствительного к регистру XML.

Ответ 11

В моем сценарии я работал над заданием, где код находился в VB.NET, а процедура, в которой десериализованные объекты из строк xml отлично работала для десятков применений, но вчера провалилась с "user xmlns = '' не было ожидаемой ошибки (когда на нее была выбрана строка xml, которая была сериализацией объекта, у которого было свойство, которое было, само по себе, сериализованным объектом). Ответы выше помогли мне решить эту проблему, приняв эту рутину, которая работала...

' DESERIALIZE OBJECT FROM XML STRING
Public Shared Function DeserializeFromXml(Of T)(ByVal xml As String) As T
  Dim response As T = Nothing
  Try
    Using reader As TextReader = New StringReader(xml)
      response = DirectCast(New XmlSerializer(GetType(T)).Deserialize(reader), T)
    End Using
  Catch ex As Exception
  End Try
  Return response
End Function

... скопируйте этот код и создайте новую процедуру, которая позволяет вызывающему абоненту указать строку "Имя атрибута корня". Новая процедура десериализовала объект "проблема" из его сериализованной строки xml без ошибок:

' DESERIALIZE OBJECT FROM XML STRING, SUPPLYING A ROOT ATTRIBUTE ELEMENT NAME
Public Shared Function DeserializeFromXmlWithRootAttribute(Of T)(ByVal xml As String, ByVal rootAttributeName As String) As T
  Dim response As T = Nothing
  Try
    Using reader As TextReader = New StringReader(xml)
      Dim xra As New XmlRootAttribute()
      xra.ElementName = rootAttributeName
      xra.IsNullable = True
      response = DirectCast(New XmlSerializer(GetType(T), xra).Deserialize(reader), T)
    End Using
  Catch ex As Exception
  End Try
  Return response
End Function

Ответ 12

Просто добавьте свой корневой элемент в Serializer. Для вашего XML-документа это user.

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

Ответ 13

В моем случае у моего xml было несколько пространств имен и атрибутов. Поэтому я использовал этот сайт для генерации объектов - https://xmltocsharp.azurewebsites.net/

И использовал приведенный ниже код для десериализации

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