IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Framework .NET Discussion :

Deserializer une collection XML


Sujet :

Framework .NET

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 33
    Points : 23
    Points
    23
    Par défaut Deserializer une collection XML
    Bonjour,

    Mon problème est le suivant : je reçois de la part d'un service REST un XML, qui contient une liste d'éléments.
    J'aimerais la "déserializer". Mais je n'y arrive pas car la balise qui contient ma liste n'est pas comprise par la classe XmlSerializer.
    Supposons que je reçoit une collection d'objet "Personne".
    Le code XML renvoyé par le webservice est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    <?xml version="1.0" encoding="UTF-8"?>
    <Personnes>
    	<Personne>
    		<Nom>Toto1</Nom>
    	</Personne>
    	<Personne>
    		<Nom>Toto2</Nom>
    	</Personne>
    </Personnes>
    En gros, le webservice englobe par une balise au pluriel la collection renvoyée.
    Je ne sais pas comment définir un objet permettant de désérializer cela.
    J'ai correctement généré une classe "Personne" grâce à xsd.exe et le xsd qui correspond.
    J'essaye de désérializer grâce à ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     XmlSerializer xs = new XmlSerializer(typeof(Personne[]));
     
                // On déserialise une liste de Personnes
                Personne[] Liste_Personne;
                using (StreamReader rd = new StreamReader("2_Personnes.xml"))
                {
                    Liste_Personne = xs.Deserialize(rd) as Personne[];
                }
    Mais cela ne marche pas. Lors de l'execution, cela lève une exception disant que la balise "Personnes" n'était pas attendu.
    C'est logique mais je ne sais pas comment contourner ce problème.

    Merci par avance.

  2. #2
    Membre confirmé Avatar de NicoL__
    Homme Profil pro
    Architecte
    Inscrit en
    Janvier 2011
    Messages
    399
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Janvier 2011
    Messages : 399
    Points : 577
    Points
    577
    Par défaut
    Comme ça vite fait je dirais qu'il faut créer une classe dont le nom importe peu ayant un propriété personnes qui est une liste de personne et desserialiser cette classe. Ne pas utiliser directement une collection.

  3. #3
    Invité
    Invité(e)
    Par défaut
    Je confirme ce que dit Nicolas.

    Sinon vu que tu dis avoir générer la classe à partir d'un XSD alors peux-tu nous la montrer ?

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 33
    Points : 23
    Points
    23
    Par défaut
    Ca ne marche hélas pas.
    En tout cas, je ne sais pas le faire marcher.

    J'ai créé la classe suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    [System.SerializableAttribute()]
    [System.Xml.Serialization.XmlRootAttribute("ListePersonne_Attribute", Namespace = "", IsNullable = false)]
    public class ListePersonne
    {
        private Personne[] _personnes;
     
        /// <remarks/>
        [System.Xml.Serialization.XmlArrayAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
        [System.Xml.Serialization.XmlArrayItemAttribute("Personne", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public Personne[] Personnes
        {
            get
            {
                return this._personnes;
            }
            set
            {
                this._personnes = value;
            }
        }
    }
    Qui se sérialize en donnant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?xml version="1.0" encoding="UTF-8"?>
    <ListePersonne_Attribute xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Personnes>
    	<Personne>
    		<Nom>Toto1</Nom>
    	</Personne>
    	<Personne>
    		<Nom>Toto2</Nom>
    	</Personne>
    </Personnes>
    </ListePersonne_Attribute>
    Ce qui est presque ce que je recherche. Mais il y a bien une balise qui représente ma classe et qui encadre ma propriété.
    En essayant de désérializer avec un serializer de type "ListePersonne"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    <?xml version="1.0" encoding="UTF-8"?>
    <Personnes>
    	<Personne>
    		<Nom>Toto1</Nom>
    	</Personne>
    	<Personne>
    		<Nom>Toto2</Nom>
    	</Personne>
    </Personnes>
    Ca ne marche pas.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Essaies le code suivant :

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    [System.SerializableAttribute()]
        [System.Xml.Serialization.XmlRootAttribute("Personnes", Namespace = "", IsNullable = false)]
        public class ListePersonne
        {
            private Personne[] _personnes;
     
            /// <remarks/>
            //[System.Xml.Serialization.XmlArrayAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
            //[System.Xml.Serialization.XmlArrayItemAttribute("Personne", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
            [System.Xml.Serialization.XmlElement("Personne")]
            public Personne[] Personnes
            {
                get
                {
                    return this._personnes;
                }
                set
                {
                    this._personnes = value;
                }
            }
        }

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 33
    Points : 23
    Points
    23
    Par défaut
    Bonjour,

    cette astuce ne marche pas.

    Quand je sérialize un élément "ListePersonne", j'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?xml version="1.0" encoding="UTF-8"?>
    <Personnes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Personnes>
    	<Personne>
    		<Nom>Toto1</Nom>
    	</Personne>
    	<Personne>
    		<Nom>Toto2</Nom>
    	</Personne>
    </Personnes>
    </Personnes>
    Et quand j'essaye de désérializer en listePersonne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?xml version="1.0" encoding="UTF-8"?>
    <Personnes>
    	<Personne>
    		<Nom>Toto1</Nom>
    	</Personne>
    	<Personne>
    		<Nom>Toto2</Nom>
    	</Personne>
    </Personnes>
    Je n'obtiens pas d'exception, mais j'obtiens un objet null.

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Avec ça, ça devrait marcher :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    XmlSerializer xs = new XmlSerializer(typeof(Personne[]), new XmlRootAttribute("Personnes"));
    (le reste du code initial est inchangé)

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 33
    Points : 23
    Points
    23
    Par défaut
    Ca marche presque avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    XmlSerializer xs = new XmlSerializer(typeof(Personne[]), new XmlRootAttribute("Personnes"));
    Le dernier problème est que ma classe "Personne" se nomme en réalité "Pn".
    Mais quand on sérialise un tableau de "Personne", la balise a pour nom "Pn" ( = le nom de la classe).

    Dans une classe, pour un propriété donnée, on peut régler cela via les propriétés instructions "[XmlArray("...")]" et "[XmlArrayItem("...")]".

    Mais comment le faire pour un simple tableau ?

    J'ai contourné le problème en créant une classe Personne qui hérite de Pn sans rien rajouter mais c'est moche.

    Sinon, j'ai trouvé une autre astuce : charger mon fichier XML dans un XmlDocument, et jouer avec les éléments, puis envoyer mon XML dans un XMLSerializer, mais c'est aussi moche.

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par losformen Voir le message
    J'ai contourné le problème en créant une classe Personne qui hérite de Pn sans rien rajouter mais c'est moche.
    Bah ce qui est moche c'est surtout une classe qui s'appelle Pn... on est supposé utiliser des noms descriptifs, Pn ça pourrait vouloir dire n'importe quoi. Pourquoi tu renommes pas tout simplement ta classe ? C'est super facile avec les outils de refactoring de Visual Studio...

    Sinon tu peux simplement coller un attribut [XmlType("Personne")] sur ta classe, ça donnera le résultat voulu.

    En fait on peut faire à peu près tout ce qu'on veut avec XmlSerializer, en jouant un peu avec les options... J'ai écrit 2 articles sur le sujet :
    La sérialisation XML avec .NET
    Aller plus loin avec la sérialisation XML

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 33
    Points : 23
    Points
    23
    Par défaut
    Merci Tomlev, ça marche et la solution est simple.

    Pour résumer ajout de l'attribut sur la classe et création d'un serializer "customisé"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    XmlSerializer xs = new XmlSerializer(typeof(Personne[]), new XmlRootAttribute("Personnes"));
    Quant à la classe qui s'appelle "Pn", non elle ne s'appelle pas comme ça. J'ai changé mon exemple car je ne peux donner les vrais noms de classe avec les vrais propriété mais la réalité est mieux conçue.

    C'est une classe partagée, je ne peux pas faire non plus ce que je veux avec.

    Et oui, y'a beaucoup d'options sur la sérialization, mais je n'arrivais pas à trouver les bons.
    Je n'avais lu que ton premier article.
    http://tlevesque.developpez.com/dotn...serialization/
    et la balise [XmlType("...")] n'apparaissait pas.

    En tout cas, je te remercie. C'est clair désormais.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 03/04/2014, 10h39
  2. Recuperer un doc xml d'une collection Exist
    Par tigunn dans le forum XQUERY/SGBD
    Réponses: 3
    Dernier message: 18/04/2012, 17h01
  3. Réponses: 7
    Dernier message: 30/06/2011, 15h16
  4. Réponses: 2
    Dernier message: 27/04/2010, 15h58
  5. [VB6] Modifier la clé d'un élément d'une collection
    Par Ricou13 dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 21/11/2002, 14h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo