{"<user xmlns = ''> non era previsto.} Deserializzazione di XML XML


213

Sto inserendo l'XML da Twitter tramite OAuth.

Sto facendo una richiesta a http://twitter.com/account/verify_credentials.xml , che restituisce il seguente 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>

Sto usando il seguente codice per deserializzare:

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

E ho il seguente per la mia Userclasse:

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

}

Ma quando sta deserializzando l'XML sopra, l'applicazione genera quanto segue:

  • $ exception {"Errore nel documento XML (2, 2)."} System.Exception {System.InvalidOperationException}

  • InnerException {"<user xmlns = ''> non previsto."} System.Exception {System.InvalidOperationException}

Ora ho cercato e la soluzione migliore che posso trovare è quella di aggiungere spazi vuoti al serializzatore quando si serializza il contenuto, ma non lo sto serializzando, quindi non posso.

Ho anche del codice per ricevere gli stati, che funziona bene.

Qualcuno può spiegarmi perché si sta verificando l'errore? Oltre a una possibile soluzione?

Grazie in anticipo.


Nel mio caso, è stato a causa della dichiarazione errata di XmlSerializer. Quindi controlla anche quello.
Mangesh,

Ho dovuto aggiungere un campo con XmlAttribute in classe. Vedi link
Stefan Varga,

Risposte:


264

Decorare l'entità radice con l'attributo XmlRoot che verrà utilizzato al momento della compilazione.

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

Oppure specificare l'attributo root durante la de serializzazione in fase di esecuzione.

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

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

6
Si potrebbe aggiungere un attributo XmlRoot alla classe msdn.microsoft.com/en-us/library/83y7df3e(VS.71).aspx [XmlRoot (Namespace = "www.contoso.com", ElementName = "MyGroupName", DataType = "string", IsNullable = true)]
David Valentine,

39
XML fa distinzione tra maiuscole e minuscole. "Utente" e "utente" sono nomi diversi.
John Saunders,

4
Ho effettuato il downvoting perché ritengo che le informazioni XmlRoot debbano essere definite sulla classe stessa, non dove vengano deserializzate. Per questo motivo, la soluzione di Junto è, a mio avviso, superiore.
GuiSim,

4
@GuiSim Stai assumendo che l'OP abbia il controllo sull'entità originale. Entrambe le risposte sono valide. Nel mio caso non riesco ad aggiungere XmlRoot all'entità in quanto viene utilizzato come parte di MessageContract. L'uso del metodo sopra funziona per il mio scenario.
Bronumski,

4
@GuiSim Non sono in disaccordo con quanto affermato dall'OP. Ho il controllo completo della mia entità radice ma non posso usare l'attributo root perché è in conflitto con l'attributo MessageContract. Entrambe le risposte sono valide e l'alternativa è stata presentata nei commenti. Il punto è che stai votando una risposta valida, non una risposta sbagliata. Se non sei d'accordo sul fatto che sia il migliore, non votare.
Bronumski,

135

Ancora più semplice è solo aggiungere le seguenti annotazioni all'inizio della lezione:

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

Semplice e diretto
mayowa ogundele,

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

2
Questo è fantastico per i casi in cui altrimenti dovresti fare affidamento sui condizionali per gli attributi.
Den Delimarsky,

2
Molto semplice e risolto completamente il mio caso. Grazie!
AW,

12

Il messaggio di errore è così vago, per me avevo questo codice:

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

Si noti che xmlSerializer è istanziato con aResponse ma alla deserializzazione l'ho lanciato accidentalmente su bResonse.


2
Ho appena avuto un problema simile. xmlserializer è stato inizializzato su typeof (T) e stavo lanciando su List <T>
nurettin,

1
Ho dichiarato XmlRoot(..)sulla classe figlio della classe ClassBgenitore ClassA. Ho usato new XmlSerializer(typeof(ClassA)invece di on ClassBe ho anche lanciato l'oggetto. Grazie per la segnalazione!
Shishir Gupta,

6

La soluzione più semplice e migliore è solo usare l' attributo XMLRoot nella tua classe, in cui desideri deserializzare.

Piace:

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

Inoltre, utilizzare il seguente assieme :

using System.Xml.Serialization;

3
Qualcuno vuole dare una spiegazione? Perché è XmlRoot()necessario l'attributo per risolvere questo problema? Ci sono 5 risposte qui che dicono "aggiungi questo codice" e non una spiegazione. Le persone rispondono 7 anni dopo ed è ancora solo "Aggiungi questo codice XmlRoot". Di tutte le risposte ho scelto la più recente per chiedere una spiegazione.
Quantic,

Grazie a @Quantic, XmlRoot ti consente di creare un nuovo valore xml anziché utilizzare il root predefinito che puoi personalizzare. È solo il tipo di decorazione che aggiungerai al tuo XML al momento della compilazione. Eliminerà alcune volte problemi di compatibilità. Spero che tu ottenga il mio punto.
Khawaja Asim,

5

Come dice John Saunders, controlla se i nomi di classe / proprietà corrispondono al maiuscolo del tuo XML. In caso contrario, si verificherà anche il problema.


2

Il mio problema era che uno dei miei elementi aveva l'attributo xmlns:

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

Indipendentemente da ciò che ho provato, l'attributo xmlns sembrava interrompere il serializzatore, quindi ho rimosso qualsiasi traccia di xmlns = "..." dal file xml:

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

e voilà! Tutto ha funzionato.

Ora analizzo il file XML per rimuovere questo attributo prima di deserializzare. Non sono sicuro del perché funzioni, forse il mio caso è diverso poiché l'elemento che contiene l'attributo xmlns non è l'elemento radice.


Il tuo file specificava che RETS-RESPONSE era nello spazio dei nomi "blahblah". Se ciò non corrispondesse al tuo schema, l'elemento non sarebbe stato trovato. Inoltre, l'aggiunta di uno spazio dei nomi predefinito causa anche molti altri problemi di riferimento.
Suncat2000

2

L'unica cosa che ha funzionato nel mio caso è stata l'uso del codice di David Valentine. Usando l'attrazione principale. nella classe Person non ha aiutato.

Ho questo semplice Xml:

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

Classe C #:

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

De-serializzazione del codice C # da un metodo principale:

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

2

Nel mio caso, il mio XML aveva più spazi dei nomi e attributi. Quindi ho usato questo sito per generare gli oggetti - https://xmltocsharp.azurewebsite.net/

E usato il codice qui sotto per deserializzare

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

Il link ha fornito un grande aiuto per deserializzare xml in classe.
smr5,

1

Il mio problema era che l'elemento root in realtà ha un xmlns = "abc123"

Quindi ho dovuto creare XmlRoot ("elementname", NameSpace = "abc123")


1

Tutto quanto sopra non ha funzionato per me, ma questo è stato: Verifica che il nome dell'elemento Root della classe sia esattamente come quello dell'XML maiuscole e minuscole .


1

Niente ha funzionato per me per questi errori TRANNE

... was not expected, 
... there is an error in XML document (1,2)
... System.FormatException Input String was not in correct format ...

Tranne questo

1- È necessario ispezionare la risposta XML come stringa (la risposta che si sta tentando di deserializzare su un oggetto)

2- Utilizzare gli strumenti online per la rimozione delle stringhe e il prettify / formatter xml

3- ASSICURARSI che la classe C # (classe principale) che si sta tentando di mappare / deserializzare la stringa xml su abbia un XmlRootAttribute che corrisponda all'elemento radice della risposta.

Exmaple:

La mia risposta XML stava fissando come:

<ShipmentCreationResponse xmlns="http://ws.aramex.net/ShippingAPI/v1/">
       <Transaction i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>
           ....

E la definizione della classe C # + gli attributi erano simili:

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

Si noti che la definizione di classe non ha " XmlRootAttribute "

[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://ws.aramex.net/ShippingAPI/v1/", IsNullable = false)]

E quando provo a de serializzare usando un metodo generico:

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

Stavo ottenendo gli errori sopra

... was not expected, ... there is an error in XML document (1,2) ...

Ora aggiungendo semplicemente "XmlRootAttribute" che ha risolto il problema per sempre e per ogni altra richiesta / risposta ho avuto un problema simile con:

[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
{
    ........
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.