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

C++ Discussion :

Récupérer un noeud spécifique avec SAX libxml2


Sujet :

C++

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2012
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 15
    Points : 5
    Points
    5
    Par défaut Récupérer un noeud spécifique avec SAX libxml2
    Bonjour à tous.

    Je suis assez nouveau en C, s'il vous plaît, soyez indulgent.
    J'ai fait de nombreuses recherches dans le but d'annihiler mon problème, sans résultat. J'espère que vous pourrez m'apporter votre aide.

    Voici mon probleme:
    Dans un programme, je dois parser des fichiers XML. Jusqu'à maintenant, j'ai utilisé le parser DOM car les fichiers étaient peu volumineux.
    Aujourd'hui, je suis confronté à un XML de plus de 60 MO.
    Je compte donc utiliser le parser SAX.

    J'ai réussi à trouver des exemples qui m'ont permis de construire un petit parser sax fonctionnel, dont voici le code:

    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
    79
    80
    81
    82
    83
    84
    #include <Riostream.h>
    #include <TList.h>
    #include <TSAXParser.h>
    #include <TXMLAttr.h>
    class SaxHandler {
    public:
       SaxHandler() { }
     
       void     OnStartDocument() { }
       void     OnEndDocument();
       void     OnStartElement(const char*, const TList*);
       void     OnEndElement(const char*);
       void     OnCharacters(const char*);
       void     OnComment(const char*);
       void     OnWarning(const char*);
       void     OnError(const char*);
       void     OnFatalError(const char*);
       void     OnCdataBlock(const char*, Int_t);
    };
     
    void SaxHandler::OnEndDocument()
    {
       cout << endl;
    }
     
    void SaxHandler::OnStartElement(const char *name, const TList *attributes)
    {
       cout << "<" << name;
     
       TXMLAttr *attr;
     
       TIter next(attributes);
       while ((attr = (TXMLAttr*) next())) {
          cout << " " << attr->GetName() << "=\"" << attr->GetValue() << "\"";
       }
     
       cout  << ">";
    }
     
    void SaxHandler::OnEndElement(const char *name)
    {
       cout << "</" << name << ">";
    }
     
    void SaxHandler::OnCharacters(const char *characters)
    {
       cout << characters;
    }
     
    void SaxHandler::OnComment(const char *text)
    {
       cout << "<!--" << text << "-->";
    }
     
    void SaxHandler::OnWarning(const char *text)
    {
       cout << "Warning: " << text << endl;
    }
     
    void SaxHandler::OnError(const char *text)
    {
       cerr << "Error: " << text << endl ;
    }
     
    void SaxHandler::OnFatalError(const char *text)
    {
       cerr << "FatalError: " << text << endl ;
    }
     
    void SaxHandler::OnCdataBlock(const char *text, Int_t len)
    {
       cout << "OnCdataBlock() " << text;
    }
     
     
     
    void SAXHandler()
    {
       TSAXParser *saxParser = new TSAXParser();
       SaxHandler *saxHandler = new SaxHandler();
     
       saxParser->ConnectToHandler("SaxHandler", saxHandler);
       saxParser->ParseFile("monfichier.xml");
    }
    Cependant, ces lignes lisent l'intégralité du fichier XML et ne récupèrent aucune valeur. J'aimerais récupérer des attributs situés dans certains noeuds spécifiques sans mettre en mémoire tout mon fichier XML. Est-ce possible ? Si oui, pouvez-vous m'aider ?


    Je vous remercie par avance,

    Froztiz

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Bonjour,

    Ton programme est écrit en C++ et non en C. Je le déplace dans le forum adéquat.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2012
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 15
    Points : 5
    Points
    5
    Par défaut
    Merci Obsidian.

    Quelqu'un a-t-il une idée pour résoudre mon problème ?

    Ou bien est-ce une question stupide que je vous pose ?
    J'espère au moins que c'est réalisable avec SAX.

  4. #4
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Là, ton programme recopie le xml sur la sortie (en gros).
    Tu n'as plus qu'à adapter OnStartElement pour récupérer les attributs que tu veux.

    D'ailleurs, pourquoi ce Riostream.h ?

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2012
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 15
    Points : 5
    Points
    5
    Par défaut
    Salut Ekleog,

    Merci pour ta réponse.

    Mon code fait déjà 700 lignes et j'utilise diverses classes dedans, d'où le Riostream.
    J'ai bien compris qu'il fallait adapter le OnStartElement, mais j'avoue ne pas connaitre la syntaxe....
    Pourrais-tu me donner un exemple ?

    Merci d'avance

  6. #6
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Mon code fait déjà 700 lignes et j'utilise diverses classes dedans, d'où le Riostream.
    Après une recherche sur internet, Riostream.h est l'équivalent de iostream en version compilateur-qui-date-vraiment.
    D'où ma question.

    J'ai bien compris qu'il fallait adapter le OnStartElement, mais j'avoue ne pas connaitre la syntaxe....
    Pourrais-tu me donner un exemple ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void SaxHandler::OnStartElement(const char *name, const TList *attributes)
    {
       TXMLAttr *attr;
       TIter next(attributes);
       while ((attr = (TXMLAttr*) next())) {
          // Ici tu vas parcourir tous les attributs un par un. GetName() te permet
          // de récupérer leur nom, et GetValue() leur valeur.
          // Par exemple,
          map[attr->GetName()] = attr->GetValue(); // Code invalide, mais je ne sais pas ce que tu veux en faire ...
       }
     
       cout  << ">";
    }

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2012
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 15
    Points : 5
    Points
    5
    Par défaut
    En fait, je voudrais récupérer la valeur de certains attributs qui sont dans certains noeuds uniquement. Le problème, c'est que pour les comparer (écrire un truc du genre if(attr->GetName() == "blabla"){ variable=attr->GetValue();}), je dois les mettre en mémoire, ce qui est couteux en temps pour un fichier de 60 Mo.
    J'ai essayé d'utiliser la formule .equal("") mais ça n'a pas fonctionné.

    Supposons que je souhaite récupérer dans le XML suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <medium name="04"
             type="bb"
             temp="250">
       <micro test1="B1" result="2"/>
       <micro test1="B2" result="7"/>
       <micro test1="C3" result="9"/>
       <micro test1="O4" result="1"/>
    <medium name="06"
             type="cc"
             temp="250">
       <micro test1="B1" result="9"/>
       <micro test1="B2" result="9"/>
       <micro test1="C3" result="9"/>
       <micro test1="O6" result="1"/>
    les valeurs result du noeud medium name 6. Comment puis-je faire sans mettre en mémoire tous les noeuds ?

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2012
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 15
    Points : 5
    Points
    5
    Par défaut
    C'est bon, j'ai trouvé une solution alternative.
    J'execute dans mon code C un script qui vient "débroussailler" mon XML.

  9. #9
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Déjà, ce n'est pas un fichier xml valide.

    Sinon, quelque chose comme (je ne garantis pas, c'est non testé) :
    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
    // Ajouter bool inMeduim06 en attribut, défaut à false
    // Ajouter std::string resultats en attribut, défaut à ""
    void SaxHandler::OnStartElement(const char *name, const TList *attributes) {
      TXMLAttr *attr;
      TIter next(attributes);
      if (strcmp(name, "medium") == 0) {
        while ((attr = (TXMLAttr*) next())) {
          if (strcmp(attr->GetName(), "name") == 0) {
            if (strcmp(attr->GetValue(), "06") == 0) {
              inMedium06 = true;
            }
          }
        }
      } else if (inMedium06) {
        while ((attr = (TXMLAttr*) next())) {
          if (strcmp(attr->GetName(), "result") == 0) {
            resultats.push_back(' ');
            resultats += attr->GetValue();
          }
        }
      }
    }
    void void SaxHandler::OnEndElement(const char *name) {
      if (strcmp(name, "medium") == 0) {
        inMedium06 = false;
      }
    }

Discussions similaires

  1. Réponses: 3
    Dernier message: 19/04/2016, 19h36
  2. [SAX] Parser un document avec SAX et récupérer les données
    Par sperca dans le forum Format d'échange (XML, JSON...)
    Réponses: 2
    Dernier message: 06/12/2009, 15h51
  3. [SAX] Récupérer une entité avec SAX sans la modifier
    Par basis2 dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 29/12/2008, 18h20
  4. [XML] Récupérer un noeud AVEC les tags.
    Par Sinclair dans le forum C#
    Réponses: 2
    Dernier message: 28/01/2008, 14h14
  5. Récupérer 10 nb différents avec un calcul aléatoire
    Par BXDSPORT dans le forum Langage
    Réponses: 3
    Dernier message: 04/08/2002, 03h35

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