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

Windows Forms Discussion :

C# Créer un objet comportant une liste d'objets depuis un XML


Sujet :

Windows Forms

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2016
    Messages : 5
    Points : 5
    Points
    5
    Par défaut C# Créer un objet comportant une liste d'objets depuis un XML
    Bonjour à tous,
    C'est mon premier message sur le forum, d'habitude j'arrive à trouver une solution en farfouillant ici et là mais cette fois, je bloque.
    Je m'excuse par avance si la question a déjà été posée. C'est à peu près sûr qu'elle l'a été, enfin j'imagine, un truc si simple et si utile, je dois pas être le premier à vouloir faire ça mais j'ai pas trouvé (ou plutôt compris) l'info qui solutionnerait mon soucis.

    Je vais essayer d'être compréhensible pour vous détailler mon soucis :
    J'ai un fichier XML que je génère par code et qui a cette architecture :
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    <ListeFiches>
        <ID>0</ID>
        <Nom>nom 1</Nom>
        <Datec>05/02/2016</Datec>
        <Vidanges>
          <Vidange>
            <IDv>1</IDv>
            <Huile>Huile0</Huile>
            <Filtre>Filtre 0</Filtre>
            <DateV>05/02/2016</DateV>
          </Vidange>
          <Vidange>
            <IDv>2</IDv>
            <Huile>Huile1</Huile>
            <Filtre>Filtre 1</Filtre>
            <DateV>05/02/2016</DateV>
          </Vidange>
          <Vidange>
            <IDv>3</IDv>
            <Huile>Huile2</Huile>
            <Filtre>Filtre 2</Filtre>
            <DateV>05/02/2016</DateV>
          </Vidange>
        </Vidanges>
        <Revision>05/02/2016</Revision>
        <CT>05/02/2016</CT>
        <Notification>True</Notification>
        <Carburants>
          <Carburant>
            <IDc>1</IDc>
            <Type>Essence</Type>
            <DateP>05/02/2016</DateP>
            <KmPa>100</KmPa>
            <KmTo>300</KmTo>
            <PrixUnitaire>2.5</PrixUnitaire>
            <PrixTotal>125</PrixTotal>
            <Volume>50</Volume>
          </Carburant>
          <Carburant>
            <IDc>2</IDc>
            <Type>Essence</Type>
            <DateP>05/03/2016</DateP>
            <KmPa>100</KmPa>
            <KmTo>300</KmTo>
            <PrixUnitaire>2.5</PrixUnitaire>
            <PrixTotal>125</PrixTotal>
            <Volume>50</Volume>
          </Carburant>
          <Carburant>
            <IDc>3</IDc>
            <Type>Essence</Type>
            <DateP>05/04/2016</DateP>
            <KmPa>100</KmPa>
            <KmTo>300</KmTo>
            <PrixUnitaire>2.5</PrixUnitaire>
            <PrixTotal>125</PrixTotal>
            <Volume>50</Volume>
          </Carburant>
        </Carburants>
        <Divers>
          <Diver>
            <IDd>1</IDd>
            <Designation>Désignation 0</Designation>
            <DateD>05/02/2016</DateD>
          </Diver>
          <Diver>
            <IDd>2</IDd>
            <Designation>Désignation 1</Designation>
            <DateD>05/03/2016</DateD>
          </Diver>
          <Diver>
            <IDd>3</IDd>
            <Designation>Désignation 2</Designation>
            <DateD>05/04/2016</DateD>
          </Diver>
        </Divers>
      </FicheEngin>
    </ListeFiches>
    La génération du XML fonctionne très bien, le fichier est bien formaté.
    Là où je bloque :
    Je dispose d'une classe FicheMecanique qui reprends les valeurs contenu entre les balises FicheEngin de mon XML.
    Cette classe FicheMecanique est construite comme ceci :
    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
    23
    24
    25
    26
     
    public class FicheMecanique 
        {
            public int ID { get; set; }
            public string Nom { get; set; }
            public DateTime DateC { get; set; }
            public List<FicheVidange> ListeVidange { get; set; }
            public DateTime DateR { get; set; }
            public DateTime DateCT { get; set; }
            public bool Notification { get; set; }
            public List<FicheCarburant> ListeCarburant { get; set; }
            public List<FicheDivers> ListeDivers { get; set; }
     
           public FicheMecanique(int id, string nom, DateTime datec, DateTime dater, DateTime datect, bool notif, List<FicheCarburant> listeCarb,
                List<FicheDivers> listeDivers, List<FicheVidange> listeVid)
            {
                this.ID = id;
                this.Nom = nom;
                this.DateC = datec;
                this.DateR = dater;
                this.DateCT = datect;
                this.Notification = notif;
                this.ListeCarburant = listeCarb;
                this.ListeDivers = listeDivers;
                this.ListeVidange = listeVid;
            }
    Et trois classes FicheCarburant, FicheDivers et FicheVidange construites comme ceci (elles se ressemblent donc je n'en met qu'une pour l'exemple) :
    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
    public class FicheVidange 
        {
            public int IDvid { get; set; }
            public DateTime DateVid { get; set; }
            public string TypeHuile { get; set; }
            public string RefFiltre { get; set; }
     
            public FicheVidange(int id, DateTime dv, string huil, string filt)
            {
                this.IDvid = id;
                this.DateVid = dv;
                this.TypeHuile = huil;
                this.RefFiltre = filt;
            }
     
        }

    Je souhaite donc parcourir mon XML et en extraire chaque FicheEngin dans une FicheMecanique (et placer chaque FicheMecanique dans une list of course).
    Je bloque sur mes "sous-noeuds" Vidanges, Carburants et Divers.
    Je n'arrive pas à parcourir ces sous noeuds pour créer la fiche correspondante (FicheVidange, FicheCarburant, FicheDivers), placer la fiche créée dans une list<FicheVidange(ou autre)>, pour compléter ma FicheMecanique qui attends en paramètre, entre autre, les 3 listes de vidange,carburant et divers.

    Pour l'instant j'ai fait ça comme code mais ça me lève une exception :
    (extrait)
    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
    23
    24
     
    listeCarburant.Clear();    // de type List<FicheCarburant>
    listeDivers.Clear();
    listeVidange.Clear();
    var fiches = from fi in xmlDoc.Descendants() select fi;    // xmlDoc est un XDocument contenant le xml que j'ai mis plus haut 
     
                    foreach (XElement xe in fiches)
                    {
                    if (xe != null)
                        {
                            var recupListCarb = from carb in xmlDoc.Descendants("Carburants") select carb;
                            foreach (XElement xel in recupListCarb)
                            {
                                if (xel != null)
                                {
                                    var ficCarb = new FicheCarburant(Convert.ToInt32(xel.Element("IDc").Value), xel.Element("Type").Value,
                                        Convert.ToDateTime(xel.Element("DateP").Value), Convert.ToDouble(xel.Element("KmPa").Value),
                                        Convert.ToDouble(xel.Element("KmTo").Value), Convert.ToDouble(xel.Element("PrixUnitaire").Value), Convert.ToDouble(xel.Element("Volume").Value));   
     
                                    listeCarburant.Add(ficCarb);
                                }
                            }
                       }
                  }
    L'exception levée est : " Exception levée : 'System.Xml.XmlException' dans System.Xml.dll " ...

    Voilà, j'espère avoir été assez claire, c'est jamais bien évident de l'être.
    Je vous remercie pour toutes propositions qui me permettrait de me débloquer.
    Je suis à peu près sûr que c'est d'une facilité enfantine mais ce n'est que lorsqu'on le sait qu'on peut le dire

  2. #2
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2016
    Messages : 5
    Points : 5
    Points
    5
    Par défaut Réponse
    J'ai finalement trouvé après avoir repris la base, c'est à dire : le plus simple est souvent la solution.

    Je l'a poste au cas où cela serve à quelqu'un...

    En faite, le soucis venait de ma requête Linq qui ne ciblait pas le bon noeud, donc après un peu de réflexion voici ce que je fait :

    (au Load de ma form)

    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
     
     
    /* Par rapport au code de mon 1er message, je ne   parcours pas le noeud Parent Vidanges ( Carburants dans le 1er message), mais directement tous les noeuds enfants Vidange (sans le s). Ce qui me permet de parcourir ensuite chaque "enfant" séparément.
    */
    var vidangenode = from vid in xmlDoc.Descendants("Vidange") select vid;   
     
    /* Je peut ensuite faire ma boucle foreach pour lire chaque noeuds enfants et créer mon objet FicheVidange et le placer
     dans une liste. */
     
                foreach(XElement xelVid in vidangenode)
                {
                    var ficheVid = new FicheVidange(Convert.ToInt32(xelVid.Element("IDv").Value), Convert.ToDateTime(xelVid.Element("DateV").Value), xelVid.Element("Huile").Value, xelVid.Element("Filtre").Value);
                    listeVidange.Add((FicheVidange)ficheVid);
     
                }
    Voilà. J'espère que cela puisse aider

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2016
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    J'ai vendu la peau de l'ours trop vite je le crains.
    Après avoir fait quelques tests et vérifications, je me suis aperçu que mon code est faux.
    En fait,il fonctionne mais ne fait pas ce que je souhaite.
    Il ne sélectionne qu'un seul sous ensemble vidange et non l'ensemble. Je suis un peu perdu.

    Je vais schématiser ce que le programme fait actuellement et ce que je souhaiterais obtenir :
    Il y a donc dans le xml plusieurs FicheEngin, chaque nœud FicheEngin possède des sous-nœuds Vidanges,Carburants,Divers, chacun de ces sous-noeuds possède à son tour des sous noeuds :
    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
    23
    24
    25
    26
    27
    28
    29
    30
    <FicheEngin>
     <ID>
     </ID>
       <Vidanges> 
        <Vidange>
             <IDv>
             </IDv>
        </Vidange>
        <Vidange>
             <IDv>
             </IDv>
        </Vidange>
      </Vidanges>
       <Carburants> 
        <Carburant>
             <IDc>
             </IDc>
        </Carburant>
        <Carburant>
             <IDc>
             </IDc>
        </Carburant>
      </Carburants>
     <Divers>
        <Diver>
          <IDd>
          </IDd>
        </Diver>
      </Divers>
    </FicheEngin>
    Le code actuel me récupére uniquement les dernière valeurs contenu dans les noeuds Vidange et de la dernière FicheEngin au lieu de me récupérer l'ensemble des vidanges pour chaque FicheEngin :

    Je souhaite obtenir pour chaque FicheEngin présent dans le xml ses listes de Vidanges,Carburants,Divers associées car je dispose d'une classe FicheMecanique qui attends en paramètre ces trois listes.
    FicheMecanique fm = new FicheMecanique(ID , List<FicheVidange>, List<FicheCarburant>,List<FicheDivers>);


    Merci d'aiguiller ma réflexion
    Ou de me conseiller un bouquin sur le C# et le Linq to Xml car je débute dans cet univers là.
    Par avance, Merci !

  4. #4
    Membre expérimenté
    Avatar de charouel
    Homme Profil pro
    Freelance
    Inscrit en
    Mars 2009
    Messages
    618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2009
    Messages : 618
    Points : 1 454
    Points
    1 454
    Billets dans le blog
    9
    Par défaut
    Tu doit serialiser, il faut que tu utilise la sérialisation dans ton cas
    Code xml : 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
    <?xml version="1.0" encoding="utf-8"?>
    <CarCollection>
    <Cars>
      <Car>
        <StockNumber>1020</StockNumber>
        <Make>Nissan</Make>
        <Model>Sentra</Model>
      </Car>
      <Car>
        <StockNumber>1010</StockNumber>
        <Make>Toyota</Make>
        <Model>Corolla</Model>
      </Car>
      <Car>
        <StockNumber>1111</StockNumber>
        <Make>Honda</Make>
        <Model>Accord</Model>
      </Car>
    </Cars>
    </CarCollection>

    les classes

    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
    [Serializable()]
    public class Car
    {
        [System.Xml.Serialization.XmlElement("StockNumber")]
        public string StockNumber { get; set; }
     
        [System.Xml.Serialization.XmlElement("Make")]
        public string Make { get; set; }
     
        [System.Xml.Serialization.XmlElement("Model")]
        public string Model { get; set; }
    }
     
     
    [Serializable()]
    [System.Xml.Serialization.XmlRoot("CarCollection")]
    public class CarCollection
    {
        [XmlArray("Cars")]
        [XmlArrayItem("Car", typeof(Car))]
        public Car[] Car { get; set; }
    }

    Fonction sérialisation
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CarCollection cars = null;
    string path = "cars.xml";
     
    XmlSerializer serializer = new XmlSerializer(typeof(CarCollection));
     
    StreamReader reader = new StreamReader(path);
    cars = (CarCollection)serializer.Deserialize(reader);
    reader.Close();

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2016
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    Tout d'abord, merci Charouel pour ta réponse.
    J'ai essayé d'implémenter ce que tu as écrit mais je n'arrive pas à le faire fonctionner, j'obtiens (dans le meilleur des cas) un ArgumentNullException lorsque je tente de lire ce qui devrait se trouver dans le CarCollection (dans ton exemple , ListeVidange pour mon cas)

    Voila ce que j'ai fait :
    Dans ma classe FicheVidange :
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    namespace GestionM
    {
    [Serializable()]
        public class FicheVidange 
        {
            [System.Xml.Serialization.XmlElement("IDv")]
            public int IDvid { get; set; }
     
            [System.Xml.Serialization.XmlElement("DateV")]
            public DateTime DateVid { get; set; }
     
            [System.Xml.Serialization.XmlElement("Huile")]
            public string TypeHuile { get; set; }
     
            [System.Xml.Serialization.XmlElement("Filtre")]
            public string RefFiltre { get; set; }
     
     
            public FicheVidange()
            {
            }
     
            public FicheVidange(int id, DateTime dv, string huil, string filt)
            {
                this.IDvid = id;
                this.DateVid = dv;
                this.TypeHuile = huil;
                this.RefFiltre = filt;
            }
     
            public override string ToString()
            {
                var s = IDvid.ToString() + "   " + TypeHuile + "   " + RefFiltre + "   " + DateVid.ToShortDateString();
                return s;
            } 
     
        }
     
        [Serializable()]
        [System.Xml.Serialization.XmlRoot("ListeFiches")]
        public class ListeVidange
        {
            [XmlArray("Vidanges")]
            [XmlArrayItem("Vidange", typeof(FicheVidange))]
            public FicheVidange[] FicheVidange { get; set; }
        }
    Et dans ma fenêtre de test, je fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     ListeVidange listeVid = new ListeVidange();
                var serializer = new XmlSerializer(typeof(ListeVidange));
                var reader = new StreamReader(filepath);
                listeVid = (ListeVidange)serializer.Deserialize(reader);
                reader.Close();
                if(listeVid.FicheVidange != null)  
                { 
                    foreach(FicheVidange d in listeVid.FicheVidange)
                    {
                        Console.WriteLine("test");
                    }
                }
    filepath = AppDomain.CurrentDomain.BaseDirectory + @"\DataXML\ListeFiches.xml";
    La boucle if ne s’exécute jamais car l'argument est null, si je ne le test pas, je lève une erreur.

    J'ai également tenter avec une autre écriture, desfois que... mais non, toujours null :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    XmlSerializer xs = new XmlSerializer(typeof(ListeVidange));
                using (StreamReader rd = new StreamReader(filepath))
                {
                    ListeVidange fm = xs.Deserialize(rd) as ListeVidange;
                    Console.WriteLine("ID : {0}", fm.FicheVidange.ElementAt(0).IDvid);
                    Console.WriteLine("Nom : {0} ", fm.FicheVidange.ElementAt(0).TypeHuile);
                }

    J'ai mis la classe ListeVidange dans le même fichier que la classe FicheVidange, est ce que ça peut poser un soucis ? (je pense pas mais bon... )

    Je ne connais pas trop le xmlserializer alors je vais le potasser pour essayer de piger comment ça marche. J'ai vu qu'il y avait un tutoriel de Thomas Levesque qui date de 2009, ça devrait m'aider j'espère.
    Encore merci de ta réponse

  6. #6
    Membre expérimenté
    Avatar de charouel
    Homme Profil pro
    Freelance
    Inscrit en
    Mars 2009
    Messages
    618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2009
    Messages : 618
    Points : 1 454
    Points
    1 454
    Billets dans le blog
    9

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2016
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    Encore merci Charouel
    J'ai résolu le problème en m'inspirant fortement du tutoriel : http://tlevesque.developpez.com/dotn...lization/#LI-B

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 19/07/2010, 09h42
  2. Réponses: 2
    Dernier message: 07/10/2008, 14h17
  3. Ajout de Node a partir d'objet contenant une liste d'objet
    Par Al_Bundy dans le forum Windows Forms
    Réponses: 4
    Dernier message: 05/08/2008, 15h35
  4. Réponses: 2
    Dernier message: 29/05/2008, 16h59
  5. afficher une liste d'objets sur une page en flow.
    Par looploop dans le forum JSF
    Réponses: 1
    Dernier message: 18/09/2007, 11h54

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