Désérialisation XML sous Android

Résolu
MGD Software Messages postés 186 Date d'inscription vendredi 1 septembre 2006 Statut Membre Dernière intervention 23 avril 2022 - 30 oct. 2020 à 16:33
@karamel Messages postés 1855 Date d'inscription vendredi 9 mai 2008 Statut Modérateur Dernière intervention 18 avril 2024 - 31 oct. 2020 à 22:35
Bonjour,

Je développe une application Android et je cherche à désérialiser une chaine XML représentant une arborescence de classes, et à reconstituer ces classes et leur contenu.
J'ai eu beau chercher sur le net, j'ai trouvé beaucoup de choses sur la sérialisation (ce qui m'a permis de construire la chaine source), mais rien sur la dé-sérialisation qui corresponde à mon besoin. A chaque recherche je tombe sur du code C# (que je maitrise assez bien) ou sur du Java qui ne fonctionne pas dans Android Studio.

Mes classes s'appellent ModbusFrames, ModbusFrame et ModbusVar et constituent une arborescence :
- La classe ModbusFrames contient une ArrayList<ModbusFrame>
- La classe ModbusFrame contient une ArrayList<ModbusVar>

Dans la chaine XML, chaque classe ModbusFrame ou ModbusVar est représentée par un noeud portant le nom de la classe. Les attributs de chaque nœud représentent les valeurs des membres de la classe associée.

Voici un exemple de chaine à analyser, générée par un XML.Serializer :
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<ModbusFrames>
  <ModbusFrame Type="Word" Address="1000" Label="Trame 0">
    <ModbusVar Index="0" Label="Frame 0 var 0" Format="" />
    <ModbusVar Index="2" Label="Frame 0 var 1" Format="0" />
    <ModbusVar Index="4" Label="Frame 0 var 2" Format="00" />
  </ModbusFrame>
  <ModbusFrame Type="Word" Address="2000" Label="Trame 1">
    <ModbusVar Index="0" Label="Frame 1 var 0" Format="" />
    <ModbusVar Index="2" Label="Frame 1 var 1" Format="0" />
    <ModbusVar Index="4" Label="Frame 1 var 2" Format="00" />
  </ModbusFrame>
  <ModbusFrame Type="Word" Address="3000" Label="Trame 2">
    <ModbusVar Index="0" Label="Frame 2 var 0" Format="" />
    <ModbusVar Index="2" Label="Frame 2 var 1" Format="0" />
    <ModbusVar Index="4" Label="Frame 2 var 2" Format="00" />
  </ModbusFrame>
</ModbusFrames>

Quelqu'un saurait-il me fournir un bout de code pour parser cette chaine ?
(Au moins lire les nœuds et leurs attributs, la gestion des classes ne devrait pas me poser de problème)

Merci d'avance

2 réponses

MGD Software Messages postés 186 Date d'inscription vendredi 1 septembre 2006 Statut Membre Dernière intervention 23 avril 2022 2
31 oct. 2020 à 18:32
Ne cherchez plus !

En attendant une réponse (qui n'est pas venue), j'ai continué à fouiller dans les bibliothèques d'Android Studio. En tapant "New XML...", j'ai parcouru la liste des objets proposés par Intellisense.
Et là, j'ai été interpellé par le mot XmlPullParser !
En parcourant ses propriétés et méthodes, j'ai découvert que c'était effectivement un objet capable de lire une chaine XML.

Et après quelques errements j'arrive maintenant parfaitement à décoder la chaine ci-avant. En désérialsant la chaine puis en le resérialisant, j'obtiens exactement le même code à l'arrivée qu'au départ, preuve que les deux fonctions sont bien symétriques. Et entre les deux, le debug a permis de vérifier que les classes étaient bien conformes à ce qui était attendu.

Et pour que ce post puisse servir à d'autres ayant le même problème, voici le code des fonctions de sérialisation et de désérialisation. Bien sûr, il est adapté à la structure de mes classes personnelles, mais je pense que l'adaptation à d'autres classes ne devrait pas être compliquée. A noter que ces deux procédures font partie de la classe de niveau supérieur (ModbusFrames en l'occurence), ce qui explique le remplacement de l'ArrayList à la fin de la désérialisation et non le renvoi d'une classe ModbusFrames.

public String Serialize() throws IllegalArgumentException, IllegalStateException, IOException {
    StringWriter output = new StringWriter();
    XmlSerializer XmlSer = Xml.newSerializer();
    XmlSer.setOutput( output );
    XmlSer.setFeature( "http://xmlpull.org/v1/doc/features.html#indent-output", true );
    XmlSer.startDocument( "UTF-8", true );

    String RootName = "ModbusFrames";
    XmlSer.startTag( "", RootName );
    for (ModbusFrame Frame : Frames) {
        XmlSer.startTag( "", "ModbusFrame" );
        int Type = Frame.getType().ordinal();
        XmlSer.attribute( "", "Type", String.valueOf(Type) );
        XmlSer.attribute( "", "Address", String.valueOf( Frame.getAdrs() ) );
        XmlSer.attribute( "", "Label", Frame.getLabel() );
        for (ModbusVar Var : Frame.getVars()) {
            XmlSer.startTag( "", "ModbusVar" );
            XmlSer.attribute( "", "Index", String.valueOf( Var.getIndex() ) );
            XmlSer.attribute( "", "Label", Var.getLabel() );
            XmlSer.attribute( "", "Format", Var.getFormat() );
            XmlSer.endTag( "", "ModbusVar" );
        }
        XmlSer.endTag( "", "ModbusFrame" );
    }
    XmlSer.endTag( "", RootName );
    XmlSer.endDocument();

    String Result = output.toString();

    return Result;
}

public void Unserialize(String xml) throws XmlPullParserException, IOException {
    ArrayList<ModbusFrame> NewFrames = null;
    ModbusFrame Frame = null;
    ModbusVar Var = null;
    StringReader input = new StringReader( xml );
    XmlPullParser Parser = Xml.newPullParser();
    Parser.setInput( input );

    int eventType = Parser.getEventType();
    while (eventType != XmlPullParser.END_DOCUMENT) {
        String TagName = Parser.getName();
        switch (eventType) {

            case XmlPullParser.START_TAG:
                // Début de la liste de trames
                if (TagName.equals( "ModbusFrames" ))
                    NewFrames = new ArrayList<ModbusFrame>();

                // Nouvelle trame
                else if (TagName.equals( "ModbusFrame" ) && NewFrames != null) {
                    Frame = new ModbusFrame();
                    for (int i = 0; i < Parser.getAttributeCount(); i++) {
                        String AttrName = Parser.getAttributeName( i );
                        String AttrValue = String.valueOf( Parser.getAttributeValue( i ) );
                        if (AttrName.equals( "Type" ))
                            Frame.setType( AttrValue );
                        else if (AttrName.equals( "Address" ))
                            Frame.setAdrs( AttrValue );
                        else if (AttrName.equals( "Label" ))
                            Frame.setLabel(AttrValue);
                    }
                }

                // Nouvelle variable dans la trame en cours
                else if (TagName.equals( "ModbusVar" ) && NewFrames != null && Frame != null) {
                    Var = new ModbusVar();    // réation de la classe
                    
                    // Recherche des attributs
                    for (int i = 0; i < Parser.getAttributeCount(); i++) {
                        String AttrName = Parser.getAttributeName( i );
                        String AttrValue = String.valueOf( Parser.getAttributeValue( i ) );
                        if(AttrName.equals("Index"))
                            Var.setIndex(AttrValue);
                        else if(AttrName.equals( "Label" ))
                            Var.setLabel(AttrValue);
                        else if(AttrName.equals( "Format" ))
                            Var.setFormat( AttrValue );
                    }
                }
                break;
                            
            // Balise de fermeture
            case XmlPullParser.END_TAG:
                if (TagName.equals( "ModbusVar" ) && NewFrames != null && Frame != null) {
                    Frame.AddVar( Var ); // Fin de la variable ModbusVar. On l'ajoute à la trame en cours
                    Var = null;
                }
                else if(TagName.equals( "ModbusFrame" ) && NewFrames != null ) {
                    NewFrames.add( Frame ); // Fin de la variable ModbusFrame. On l'ajoute à la liste des frames
                    Frame = null;
                }
                else if(TagName.equals( "ModbusFrames" ))
                    Frames = NewFrames; // Fin des frames : on remplace la liste de la classe en cours
                break;
        }
       eventType =  Parser.next();
    }
}


0
@karamel Messages postés 1855 Date d'inscription vendredi 9 mai 2008 Statut Modérateur Dernière intervention 18 avril 2024 153
31 oct. 2020 à 22:35
Ca servira pour le prochain qui aura le même problème :)
0
Rejoignez-nous