Parser un fichier xml

Signaler
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
-
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
-
Bonsoir,

Je voulais parser mon fichier XML pouyr extraire certaines informations pour les utiliser dans mon programme C.

J'ai trouvé la librairie libxml2 qui est codée en C et qui possède deux méthodes DOM et SAX.

J'ai bien installé libxml2 et j'ai décidé de travailler avec la méthode SAX qui permet de parser des fichiers XML assez grand et n'est pas gourmande en mémoire.

J'ai trouvé des exemples en général et non simples pour un débutant sur le site officiel de libxml2. Ces exemples sont plus pour la méthode DOM. Je ne trouve pas un exemple pour SAX.

- Est ce que il y a quelqu'un qui a rencontré ce type de problème ?

- Pouvez vous me donner un exemple typique pour que j'applique sur mon fichier XML car j'ai besoin des informations qui se trouvent dans le dernier noeud de mon fichier XML ?

Merci.

208 réponses

Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,

Je voulais faire une modification sur la fonction suivante:

void DisplayConceptInfos(int index, int showExtent, FILE *fp) {

REF* ref;



// On valide la valeur de l'index

if (index>=0 && index<_countCpt) {

if (showExtent) {

ref = _concepts[index].extent;
 
if (ref) {

while (ref) {

if (ref->reference)

fprintf(fp,"%s ", ref->reference);

ref = ref->next;

}

fprintf(fp,": ");

}

}



ref = _concepts[index].intent;

while (ref) {

if (ref->reference)

fprintf(fp,"%s ", ref->reference);

ref = ref->next;

}

fprintf(fp,"\n");	

}

}



de façon d'afficher dans le fichier de descripteur fp les valeurs de 'intent' de chaque 'id'. Sauf si on a la valeur de 'intent' de premier 'id' est vide alors on ne l'affiche pas. Et si on a la valeur de 'extent' de dernier 'id' est vide alors on ne l'affiche pas sa valeur 'intent'.

par exemple si on prend le fichier xml suivant "input.xml":
<Galicia_Document>
<Lattice numberObj="4" numberAtt="4" numberCpt="16">
<Name>lattice(Ctx_0)</Name>
<Object>3</Object>
<Object>2</Object>
<Object>1</Object>
<Object>4</Object>
d
b
c
a
<Concept>
 1 
<Extent>
<Object_Ref>3</Object_Ref>
<Object_Ref>2</Object_Ref>
<Object_Ref>1</Object_Ref>
<Object_Ref>4</Object_Ref>
</Extent>




</Concept>
<Concept>
 16 
<Extent>
<Object_Ref>2</Object_Ref>
<Object_Ref>1</Object_Ref>
<Object_Ref>4</Object_Ref>
</Extent>

d


<Concept_Ref>1</Concept_Ref>

</Concept>
<Concept>
 2 
<Extent>
<Object_Ref>3</Object_Ref>
<Object_Ref>2</Object_Ref>
<Object_Ref>1</Object_Ref>
</Extent>

a


<Concept_Ref>1</Concept_Ref>

</Concept>
<Concept>
 8 
<Extent>
<Object_Ref>3</Object_Ref>
<Object_Ref>2</Object_Ref>
<Object_Ref>4</Object_Ref>
</Extent>

c


<Concept_Ref>1</Concept_Ref>

</Concept>
<Concept>
 4 
<Extent>
<Object_Ref>3</Object_Ref>
<Object_Ref>1</Object_Ref>
<Object_Ref>4</Object_Ref>
</Extent>

b


<Concept_Ref>1</Concept_Ref>

</Concept>
<Concept>
 14 
<Extent>
<Object_Ref>1</Object_Ref>
<Object_Ref>4</Object_Ref>
</Extent>

d
b


<Concept_Ref>16</Concept_Ref>
<Concept_Ref>4</Concept_Ref>

</Concept>
<Concept>
 15 
<Extent>
<Object_Ref>2</Object_Ref>
<Object_Ref>1</Object_Ref>
</Extent>

d
a


<Concept_Ref>16</Concept_Ref>
<Concept_Ref>2</Concept_Ref>

</Concept>
<Concept>
 6 
<Extent>
<Object_Ref>3</Object_Ref>
<Object_Ref>4</Object_Ref>
</Extent>

b
c


<Concept_Ref>8</Concept_Ref>
<Concept_Ref>4</Concept_Ref>

</Concept>
<Concept>
 3 
<Extent>
<Object_Ref>3</Object_Ref>
<Object_Ref>1</Object_Ref>
</Extent>

b
a


<Concept_Ref>2</Concept_Ref>
<Concept_Ref>4</Concept_Ref>

</Concept>
<Concept>
 13 
<Extent>
<Object_Ref>2</Object_Ref>
<Object_Ref>4</Object_Ref>
</Extent>

d
c


<Concept_Ref>16</Concept_Ref>
<Concept_Ref>8</Concept_Ref>

</Concept>
<Concept>
 7 
<Extent>
<Object_Ref>3</Object_Ref>
<Object_Ref>2</Object_Ref>
</Extent>

c
a


<Concept_Ref>2</Concept_Ref>
<Concept_Ref>8</Concept_Ref>

</Concept>
<Concept>
 10 
<Extent>
<Object_Ref>2</Object_Ref>
</Extent>

d
c
a


<Concept_Ref>15</Concept_Ref>
<Concept_Ref>13</Concept_Ref>
<Concept_Ref>7</Concept_Ref>

</Concept>
<Concept>
 11 
<Extent>
<Object_Ref>1</Object_Ref>
</Extent>

d
b
a


<Concept_Ref>14</Concept_Ref>
<Concept_Ref>15</Concept_Ref>
<Concept_Ref>3</Concept_Ref>

</Concept>
<Concept>
 5 
<Extent>
<Object_Ref>3</Object_Ref>
</Extent>

b
c
a


<Concept_Ref>6</Concept_Ref>
<Concept_Ref>3</Concept_Ref>
<Concept_Ref>7</Concept_Ref>

</Concept>
<Concept>
 12 
<Extent>
<Object_Ref>4</Object_Ref>
</Extent>

d
b
c


<Concept_Ref>14</Concept_Ref>
<Concept_Ref>6</Concept_Ref>
<Concept_Ref>13</Concept_Ref>

</Concept>
<Concept>
 9 
<Extent>
</Extent>

d
b
c
a


<Concept_Ref>10</Concept_Ref>
<Concept_Ref>11</Concept_Ref>
<Concept_Ref>5</Concept_Ref>
<Concept_Ref>12</Concept_Ref>

</Concept>
</Lattice>
</Galicia_Document>


on appelle la fonction:
DisplayConceptInfos(i, 0,fp);



On obtient le fichier résultat de descripteur fp:


d
a
c
b
d b
d a
b c
b a
d c
c a
d c a
d b a
b c a
d b c
d b c a


Vous remarquez que ce fichier résultat contient une première ligne vide
et comme dernière ligne "d b c a"
or "d b c a" sont 'extent' est vide.

Donc, d'après les conditions décrites on doit obtenir le résultat suivant:


d
a
c
b
d b
d a
b c
b a
d c
c a
d c a
d b a
b c a
d b c


Donc, ce fichier souhaité obtenu ne contient pas une première ligne vide et ne contient pas en dernière ligne "d b c a".

J'ai besoin de votre aide.

Que proposez vous ?

Merci.
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,

J'ai besoin de votre aide concernant ma dernière demande.
Le reste de mon travail se base sur votre réponse.

Merci.
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,

Voici mon essai :

void DisplayConceptInfos(int index, int showExtent, FILE *fp) {

REF* ref; REF* ref1;



// On valide la valeur de l'index

if (index>=0 && index<_countCpt) {

if (showExtent) {

ref = _concepts[index].extent;
 
if (ref) {

while (ref) {

if (ref->reference)

fprintf(fp,"%s ", ref->reference);

ref = ref->next;

}

fprintf(fp,": ");

}

}



ref = _concepts[index].intent;
ref1 = _concepts[index].extent;

while (ref) {

if (ref->reference && ref1->reference)

fprintf(fp,"%s ", ref->reference);

ref = ref->next;

}

fprintf(fp,"\n");	

}

}


Mais, ce code ne donne pas le résultat souhaité.

Que proposez vous ?

Merci.
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,

Merci. J'ai trouvé la solution de ma dernière demande.

J'ai fait beaucoup des tests. Mais il m'arrive toutefois lorsque je lance l'exécution avec débogage de mon programme C alors j'obtiens l'exception suivante:

<citation>Exception non gérée à 0x00414d6b dans test.exe : 0xC0000005: Violation d'accès lors de la lecture de l'emplacement 0xfeeefef2.</citation>

Voici la trace de varibles:
<citation>
- <couleur nom="bleu">ref</couleur> 0xfeeefeee {reference=??? next=??? } REF *
- <couleur nom="rouge">reference</couleur> CXX0030: Erreur : impossible d'évaluer l'expression
- <couleur nom="rouge">next</couleur> CXX0030: Erreur : impossible d'évaluer l'expression </citation>

Et comme structure de données j'utilise la liste chainée:

typedef struct {

char* reference; // la donnée proprement dite

void* next;      // pointeur vers la reference suivante (ou 0 s'il n'y a plus de donnée) 

} REF;


le débogage gére l'exception dans la partie de fonction :
void characters(void* user_data, const xmlChar *ch, int len) {


Et exactement le flèche jaune pointe sur l'instruction suivante :
while(ref->next)


qui fait partie du code suivant :
if (ref) {

// La liste contient au moins une cellule.

// On va parcourir la liste a la recherche de la dernière cellule (celle qui à le pointeur next à NULL)
while(ref->next)
ref = (REF*)ref->next;
ref->next = newRef;

}


Que proposez vous comme solution ?

Merci.
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Voici la trace de varibles:

- ref 0xfeeefeee {reference=??? next=??? } REF *
- reference CXX0030: Erreur : impossible d'évaluer l'expression
- next CXX0030: Erreur : impossible d'évaluer l'expression
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,

J'ai besoin de votre aide.

Merci.
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,

Je lance l'exécution avec débogage de mon programme C (en visual studio) alors j'obtiens
l'exception suivante:
Exception non gérée à 0x00414d6b dans test.exe : 0xC0000005: Violation d'accès lors de la lecture de l'emplacement 0xfeeefef2.


Voici la trace de varibles:
- ref 0xfeeefeee {reference= ??? next=??? } REF *
- reference CXX0030: Erreur : impossible d'évaluer l'expression
- next CXX0030: Erreur : impossible d'évaluer l'expression


Et comme structure de données j'utilise la liste chainée:

typedef struct REF {
 
char* reference; // la donnée proprement dite
struct REF* next; // pointeur vers la reference suivante (ou 0 s'il n'y a plus de donnée) 
}REF;



Le débogage gère l'exception dans la partie du fonction suivante :

void characters(void* user_data, const xmlChar *ch, int len) {
 
if (_inID && len) {
 
// On va enregistrer l'ID, mais en supprimant les espaces qui semblent s'être introduits   5  
 
while(len>1 && *ch ==32) {
 
len--;
 
ch+=sizeof(xmlChar);
 
}
 
 
 
// On supprime également les espaces qui suivent la valeur.
 
while(len>1 && *(ch+len-1)==32)
 
len--;
 
 
 
_concepts[_currentCpt].ID = (char*)malloc(len+1);
 
strncpy(_concepts[_currentCpt].ID, ch, len);
 
*(_concepts[_currentCpt].ID+len) = 0;
 
_inID = 0;
 
}
 
else if ((_inIntent || _inUpperCovers || _inExtent) && len)
 
{	
 
// lien vers les references du concept courant
 
REF** source;
 
REF* ref;
 
REF* newRef;
 
 
 
if (_inIntent)
 
source = &(_concepts[_currentCpt].intent);
 
else if (_inUpperCovers)
 
source = &(_concepts[_currentCpt].upperCovers);
 
else if (_inExtent)
 
source = &(_concepts[_currentCpt].extent);
 
 
 
ref = *source;
 
 
 
// on créé une nouvelle reference
 
newRef = (REF*)calloc(1, sizeof(REF));
 
 
 
// permet de relier la nouvelle reference a la structure (liste chainee)
 
if (ref) {
 
// La liste contient au moins une cellule.
 
// On va parcourir la liste a la recherche de la dernière cellule (celle qui à le pointeur next à NULL)
 
while(ref->next)
 
ref = (REF*)ref->next;
 
ref->next = newRef;
 
}
 
else
 
*source = newRef; // Première cellule de la liste chainée
 
 
 
// on recopie la donnée
 
newRef->reference = (char*)malloc(len+1);
 
strncpy(newRef->reference, ch, len);
 
// 0 terminal de la chaine de caractères
 
*(newRef->reference+len) = 0;	
 
 
 
// Remise à 0 des flags de position
 
_inIntent _inUpperCovers _inExtent = 0;
 
}
 
}


Et exactement le flèche jaune pointe sur l'instruction suivante :
while(ref->next)


qui fait partie du code suivant de la fonction au dessus:
if (ref) {
 
// la liste contient au moins une cellule.
 
// on va parcourir la liste a la recherche de la dernière cellule (celle qui à le pointeur next à null)
while(ref->next)
ref = (ref*)ref->next;
ref->next = newref;
 
}


Donc, la structure de liste n'est pas la cause de cette exception.

concernant l'exception 0xfeeefeee:
Sous Windows, 0xfeeefeee indique une zone mémoire qui vient d'être libérée (par un free() ou équivalent).

Dans google, Je trouve cette information sur 0xfeeefeee:

Il est souvent utile de connaitre le code de memoire en mode debug.
Bien souvent les problemes de bases en C++ sont lie a la manipulation de la memoire (pointer NULL, non initialise, variable effacee mais reutilisee…).
Ceux a connaitre par coeur sont 0xcdcdcdcd qui veut dire non initalise et 0xfeeefeee qui veut dire deja efface.

Voici le lien:
http://jeremy.chatelaine.name/blog/p...t-du-debuggage

Je souhaite que vous m'aidez.

Merci.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
en lisant un deuxieme ou plus fichier, non ?

Renfield - Admin CodeS-SourceS - MVP Visual Basic
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Oui.
Pour un seul fichier pas des problèmes.
Mais lorsque j'ai plusieurs fichiers et j'ai fait les deux fonctions 'lire fichier()' et 'cleanup()' successives pour chaque fichier dans chaque itération de la boucle.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
l'important est que tu passes bien ici :

_concepts = (CONCEPT*)calloc(_countCpt, sizeof(CONCEPT));


Renfield - Admin CodeS-SourceS - MVP Visual Basic
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Que proposez vous comme solution ?
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
que tu t'assures de bien passer par cette instruction

Renfield - Admin CodeS-SourceS - MVP Visual Basic
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Cette instruction :

_concepts = (CONCEPT*)calloc(_countCpt, sizeof(CONCEPT));

existe dans la fonction 'startElement'
et non pas dans la fonction 'characters'

Or l'exception est dans la fonction 'characters'
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
Passes tu bien par cette instruction ?

lorsque tu tentes d'accéder a ce tableau _concepts, il faut qu'il soit créé, non ?

si ca lève un exception dans characters, ça ne veut en rien dire que le souci viens de characters !

Renfield - Admin CodeS-SourceS - MVP Visual Basic
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Passes tu bien par cette instruction ?

Comment je vais vérifier si se passe bien ou non ?

lorsque tu tentes d'accéder a ce tableau _concepts, il faut qu'il soit créé, non ?


Oui.

si ca lève un exception dans characters, ça ne veut en rien dire que le souci viens de characters !


Oui.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
tu places un point d'arrêt sur cette ligne et tu lances l'execution...


Renfield - Admin CodeS-SourceS - MVP Visual Basic
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
j'ai placé un point d'arrêt sur cette ligne

_concepts = (CONCEPT*)calloc(_countCpt, sizeof(CONCEPT)); 


et J'ai lancé l'exécution avec le débogage.

Voici la trace des variables:


_concepts 0x00000000 {ID=??? intent=??? upperCovers=??? ...} CONCEPT *

ID CXX0030: Erreur : impossible d'évaluer l'expression
intent CXX0017: Erreur : symbole "" introuvable
upperCovers CXX0030: Erreur : impossible d'évaluer l'expression
extent CXX0030: Erreur : impossible d'évaluer l'expression

_countCpt 4 int


attrs 0x0035f890 const unsigned char * *

0x0035e45c "numberObj" const unsigned char* 110 'n' const unsigned char


attrs[i+1] 0x0035f920 "4" const unsigned char *
52 '4' const unsigned char


i 4 int
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
c'est au deuxième passage, ça, où au premier ?

Pour le premier, on s'en fiche. c'est important de passer par cette instruction pour le deuxieme fichier et ceux qui suivent...

Renfield - Admin CodeS-SourceS - MVP Visual Basic
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Je continue le débogage avec F5
Les valeurs précédents changent un peu :

_concepts 0x003d2cc0 {ID=0x20632062 incorrect intent=0x000a2064 upperCovers=0xfdfdfdfd ...} CONCEPT *

+ ID 0x20632062 incorrect char *
CXX0030: Erreur : impossible d'évaluer l'expression

+ intent 0x000a2064
{reference=??? next=??? } REF *
reference CXX0030: Erreur : impossible d'évaluer l'expression
next CXX0030: Erreur : impossible d'évaluer l'expression


+ upperCovers 0xfdfdfdfd {reference=??? next=??? } REF *

reference CXX0030: Erreur : impossible d'évaluer l'expression
next CXX0030: Erreur : impossible d'évaluer l'expression


+ extent 0xabababab {reference=??? next=??? } REF *

reference CXX0030: Erreur : impossible d'évaluer l'expression
next CXX0030: Erreur : impossible d'évaluer l'expression


_countCpt 7 int


attrs 0x0035e490 const unsigned char * *

0x0035d5cc "numberObj" const unsigned char *
110 'n' const unsigned char


attrs[i+1] 0x0035e500 "7" const unsigned char *

55 '7' const unsigned char


i 4 int



Je vais F5 autre fois alors le débogage
s'arrête au niveau l'instruction

while(ref->next)
de la fonction 'characters'

il m'affiche :

Exception non gérée à 0x00414e1b dans chabnasri.exe : 0xC0000005: Violation d'accès lors de la lecture de l'emplacement 0xfeeefef2.


et je ceci comme trace de variable:
-ref 0xfeeefeee {reference=??? next=??? } REF *
reference CXX0030: Erreur : impossible d'évaluer l'expression
next CXX0030: Erreur : impossible d'évaluer l'expression
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
Bon, ben je testes, puisque tu semble perdu...

suffit d'ajouter:

_currentCpt = -1;

a la fin de cleanup

c'est tout de même pas sorcier....

on voit _countCpt = 11 et _currentCPt qui vaut également 11
c'est une configuration impossible.

d'autre part, on voit bien l'initialisation

int _currentCpt = -1;

on a donc une valeur particulière pour le premier fichier. valeur qu'il nous fauut retrouver au démarrage de l'analyse de tout fichier.

Renfield - Admin CodeS-SourceS - MVP Visual Basic