Parser un fichier xml

boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 - 18 août 2009 à 21:46
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 - 24 nov. 2009 à 22:51
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

boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
28 oct. 2009 à 08:59
Bonjour,

Oui. Je n'ai pas compris le test.

Oui. j'ai utilisé deux autres variables _countObj et _countAtt.

Comment vous allez attribuer numberobj="4" à _countObj et numberatt="4" à _countAtt ?

S'il vous plait, quelle solution vous proposez car j'ai besoin de ce résultat dans la suite de mon programme ?

Merci.
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
28 oct. 2009 à 09:06
ok................
on va tenter d'expliciter le code...

void startElement(void *user_data, 	const xmlChar *name, const xmlChar **attrs){
int i;
// Si on est sur un Lattice...
if (!xmlStrcmp(name, (xmlChar*)"Lattice") && attrs) {
// On parcoure les attributs
for (i = 0; attrs[i]; i+=2) {
// Jusqu'à trouver l'atribut numberCpt
            if (!xmlStrcmp(attrs[i], (xmlChar*)"numberCpt")) {
// Que l'on mémorise (strtol permet d'analyser la valeur texte, pour en faire une valeur numérique)
_countCpt = strtol((const char*)attrs[i+1],NULL,0);
_countObj = strtol((const char*)attrs[i+1],NULL,0);
_countAtt = strtol((const char*)attrs[i+1],NULL,0);


void Lecture_d'une_nouvelle_balise_xml
if (name = "Lattice") && il y a des attributs) {
          Pour chaque attribut:
            if (Nom de l'attribut = "numberCpt") {
               _countCpt = Valeur de l'attribut numberCpt (transformé en numérique))
               _countObj = Valeur de l'attribut numberCpt (transformé en numérique))
              _countAtt = Valeur de l'attribut numberCpt (transformé en numérique))



est-ce que cela t'eclaire un peu sur erreur ?

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
28 oct. 2009 à 09:28
C'est à dire il faut faire trois tests séparés:

if (Nom de l'attribut = "numberCpt") {
_countCpt = Valeur de l'attribut numberCpt (transformé en numérique))

if (Nom de l'attribut = "numberobj") {
_countObj = Valeur de l'attribut numberCpt (transformé en numérique))

if (Nom de l'attribut = "numberatt") {
_countAtt = Valeur de l'attribut numberCpt (transformé en numérique))


C'est juste de mettre ?

if (!xmlStrcmp(attrs[i], (xmlChar*)"numberCpt")) 

_countCpt = strtol((const char*)attrs[i+1],NULL,0);

if (!xmlStrcmp(attrs[i], (xmlChar*)"numberobj")) 

_countObj = strtol((const char*)attrs[i+1],NULL,0);

if (!xmlStrcmp(attrs[i], (xmlChar*)"numberatt")) 

_countAtt = strtol((const char*)attrs[i+1],NULL,0);
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
28 oct. 2009 à 10:01
oui. Comme on dit, tu comprend vite, mais faut t'expliquer longtemps.

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
28 oct. 2009 à 20:10
Bonjour,

Voici le code complet de 'startElement':

void startElement(void *user_data, 	const xmlChar *name, const xmlChar **attrs){

int i;

// Si on est sur un Lattice...

if (!xmlStrcmp(name, (xmlChar*)"Lattice") && attrs) {

// On parcoure les attributs

for (i = 0; attrs[i]; i+=2) {

// Jusqu'à trouver l'atribut numberCpt

            if (!xmlStrcmp(attrs[i], (xmlChar*)"numberCpt")) {

// Que l'on mémorise (strtol permet d'analyser la valeur texte, pour en faire une valeur numérique)

_countCpt = strtol((const char*)attrs[i+1],NULL,0);

// on alloue un tableau qui va contenir les concepts.

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

break; // inutile de considérer les attributs suivants

            }

if (!xmlStrcmp(attrs[i], (xmlChar*)"numberobj")) 

_countObj = strtol((const char*)attrs[i+1],NULL,0);

if (!xmlStrcmp(attrs[i], (xmlChar*)"numberatt")) 

_countAtt = strtol((const char*)attrs[i+1],NULL,0);


        }

}

else if (!xmlStrcmp(name, (xmlChar*)"Concept") && _countCpt)

_currentCpt++;

else if (!xmlStrcmp(name, (xmlChar*)"Concept_Ref") && _countCpt)

_inUpperCovers = 1;

else if (!xmlStrcmp(name, (xmlChar*)"Attribute_Ref"))

_inIntent = 1;

else if (!xmlStrcmp(name, (xmlChar*)"Object_Ref"))

_inExtent = 1;

else if (!xmlStrcmp(name, (xmlChar*)"ID"))

_inID = 1;

}


J'obtiens comme résultat:

Le nombre d'objet : 0
Le nombre d'attribut : 4
Le nombre de concept : 16



Je n'obtiens pas la bonne valeur pour le nombre d'objet.

Le résultat souhaité obtenu est :

Le nombre d'objet : 4
Le nombre d'attribut : 4
Le nombre de concept : 16



Que proposez vous ?

Merci
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
28 oct. 2009 à 22:04
Attention à la casse...

numberobj est different de numberObj


Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
29 oct. 2009 à 10:34
Bonjour,

Oui comme vous dites c'est un problème de casse.
Merci beaucoup pour votre aide.

J'ai une demande et j'ai besoin votre conseil. En réalité, J'ai fichier XML "input.xml" de taille volumineux. Pour lire ce fichier, j'ai utilisé la fonction 'lire_fichier(nom de fichier)'.
Dans mon cas, je dois décomposer ce fichier xml en plusieurs fichiers XML selon des critères bien définis.
Supposons que N est le nombre de ces fichiers décomposés.

Je vais faire le même traitement X pour chacun de ces N fichiers

Voici une partie code:

for(i=1;i <= N;i++)
{
 
 sprintf(tmp,"input%d",i);
 lire_fichier(tmp);
 //le même traitement  X
..........
............

}


J'ai testé ce code sur ma machine alors ceci prendre beaucoup de temps.

Mon but est d'avoir le temps d'exécution le moins possible.

Est ce que c'est possible d'avoir un temps plus longue si on a travaille sur les N fichiers au lieu de travailler sur un seul fichier ou bien ceci dépend d'autres facteurs?

Est ce que la fonction 'lire_fichier' est couteuse ?

Dans mon cas, est ce que le mécanisme de parallélisme est possible ? c'est à dire on exécute chaque traitement sur une machine portant un fichier et donc on va utiliser N machines ?
C'est à dire on lance le traitement en même temps. Mais, ceci garantie que on va obtenir le résultat en un temps le moins possible ?

Que proposez vous

Merci.
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
30 oct. 2009 à 11:19
Bonjour,

J'ai besoin de votre aide.
Je serais très contente pour toute proposition.

Merci.
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
30 oct. 2009 à 11:37
je ne puis te répondre...
a toi de voir si c'est trop long...

je t'ai dit de ne pas générer des fichiers... tu as souhaité en générer...

les temps d'accès disque sont couteux, surtout en ecriture.


Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
30 oct. 2009 à 12:05
Oui. vous avez raison.
Tout mon travail est basé sur les fichiers puisque les traitements intermédiaires et les résultats finaux sont stockés dans des fichiers.

Avec quoi les fichiers seront remplacés ?

Est ce que on peut exploiter directement les résultats trouvés dans votre solution sans passer par les fichiers ?

S'il vous plait aidez moi car je suis bloquée.

Merci.
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
30 oct. 2009 à 12:20
Je t'ai maintes fois dit qu'une fois les données en mémoire, il était INUTILE et COUTEUX de générer des fichiers intermédiaires.

des fichier finaux, en tant que solution, oui, des fichiers intermédiaires, non.

a quoi bon ecrire dans un fichier pui s'embeter a le relire ensuite ? tout est deja en mémoire, prêt, découpé...

Maintenant, tu as une solution qui semble fonctionner, tu peux rester comme ça...

ou archiver tout le projet, le dupliquer pour tenter d'éviter la création de fichiers, mais cela me semble hors de ta portée.

a toi de bien tout comprendre, d'analyser le probleme, de RELEVER TES MANCHES et de me prouver (et à toi même) que tu en es capable.



Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
30 oct. 2009 à 13:28
Bonjour,

Supposons que on a le fichier suivnat xml '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>


D'après votre aide, nous arrivons à déterminer et sauvegarder dans un fichier 'resultat.txt' tous les valeurs de
Nous avons la fonction suivant qui rempli le fichier resultat:
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;
if (_concepts[index].extent && ref) {

while (ref) { 

if (ref->reference)

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

ref = ref->next;

} 
 
  fprintf(fp,"\n");	
}
}

}



J'ai besoin le contenu de ce fichier resultat qui est un résultat intermédiaire que je vais utiliser dans la suite de mon programme.

Dans la suite de mon programme je vais lire le fichier de descripteur fp dans la fonction 'DisplayConceptInfos' car il contient les informations (les valeurs de ) que je vais les utiliser.

Si je n'utilise pas cette fonction 'DisplayConceptInfos' alors où je trouve cette information dans votre solution?

J'ai besoin que vous m'aidez.

Merci.
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
30 oct. 2009 à 13:34
dans _concepts

ca contient toutes les données extraites du fichier

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
30 oct. 2009 à 14:33
Oui '_concepts' est une structure
Voici la structure complète que vous l'avez proposez dans la solution :
typedef struct REF {

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

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



// Structure décrivant les <Concept>

typedef struct {

char* ID;         // Valeur de l'Id

REF* intent;      // Liste des  de l'

REF* upperCovers; // Liste des <Concept_Ref> de l'

REF* extent;      // Liste des <Object_Ref> de l'<extent>

} CONCEPT ;




Comment je vais parcourir cette structure '_concept' pour lire à chaque fois la valeur de pour l'utiliser après dans la suite de mon programme ?

Merci.
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
30 oct. 2009 à 14:53
_concepts est une structure oui, qui contient la 'tête' de plusieurs listes chainées qui permettent de stocker facilement et en toute rapidité l'ensemble des tableaux extraits de ton fichier XML, oui.

maintenant, je pense que tu as mal compris le but de ce site.

ce n'est pas un site où on donne du code ni une solution pour que cela fonctionne chez toi complètement ni même directement.

Le but est tout de même que tu en tires des leçons, que tu analyses ce qui t'es proposé pour en apprendre quelque chose, non ?

tu veux savoir comment récupérer les infos du tableau _concepts ?

c'est très précisément ce que fait DisplayConceptInfos, qui n'est, comme je l'ai mis en commentaire, là qu'à titre d'exemple de l'utilisation de _concepts.

ici, on y génère un fichier resultat.txt, mais on aurait très ben pu calculer le minimum dans tel ou tel cas...


tu as un problème donné a résoudre..OK
tu as divisé ce problème en plus petits, plus simples à résoudre..OK

mais tu as loupé une marche. la liaison entre ces deux étapes.
Elles sont distinctes, certes, mais exploitent les mêmes données.

relis, donc, les différents posts, le code que tu as obtenu, les commentaires de code que tu as réclamé... tout ce qui pourrait faire que tu comprennne mieux son fonctionnement ; sa logique.

Je ne souhaites pas être cassant ou blessant. Je me permet juste un léger recadrage.

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
30 oct. 2009 à 15:13
Le but est tout de même que tu en tires des leçons, que tu analyses ce qui t'es proposé pour en apprendre quelque chose, non ?


Oui. c'est vrai et ce qui est le plus important.


tu veux savoir comment récupérer les infos du tableau _concepts ?


Oui.

En réalité, j'ai perdu ma concentration car après le travail que j'ai le fait alors je trouve que dois refaire une partie importante de mon travail.

Je voulais que vous m'aidez.

Merci.
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
30 oct. 2009 à 15:25
euh...
tu veux savoir comment récupérer les infos du tableau _concepts ?

c'est très précisément ce que fait DisplayConceptInfos [...]
ici, on y génère un fichier resultat.txt, mais on aurait très ben pu calculer le minimum dans tel ou tel cas...


en gros, tu as déjà tout ce qu'il faut pour savoir lire les infos dans _concepts.

c'est un bête tableau.
chaque cellule de ce tableau représente un <concept> dans ton fichier XML

cette structure permet entre autre de conserver tous les attribute_ref de tes balises

mais tu le sais déjà j'imagine.

Sais tu ce qu'est une liste chaînée ?
T'es tu renserigné sur la chose ?

Jimagine que c'est cette particularité de mon code qui te bloque...
Elles sont pourtant une base important de la programmation.

la structure concept stocké un pointeur vers une autre structure, générique, qui stocke la valeur de notre attribute_ref ainsi qu'un pointeur vers la prochaine cellule générique.
Ainsi de suite jusqu'a ariver à la derniere cellule, qui à la valeur NULL comme pointeur vers une prochaine cellule, pour indiquer qu'il s'agissait de la derniere cellule.

en gros:


_Concepts[0]
..intent =>..attribute_ref
.............next...=>..attribute_ref
........................next...=>...attribute_ref
....................................next.=.NULL
_Concepts[1]
..intent =>..attribute_ref
.............next...=>..attribute_ref
........................next.=.NULL





Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
31 oct. 2009 à 08:02
Bonjour,

Sais tu ce qu'est une liste chaînée ?
T'es tu renserigné sur la chose ?

Oui.

1)
Je vais refaire une grande partie de mon travail car j'ai mal choisi les structures des données car les accès fichiers sont plus coûteux. Tout mon travail se base sur les fichiers même les résultats intermédiaires. Le but de mon travail est de trouver une solution à mon problème mais de plus minimiser le plus possible le temps d'exécution.

Mais, lorsque j'ai testé le temps de l'exécution CPU concernant la comparaison de deux fichiers selon les critères bien définis alors j'ai remarqué que le temps est devenir très longue si nous avons des fichiers avec des centaines lignes.

On va lire chaque ligne de fichier 1 et le compare avec tous les lignes de fichier 2. C'est très couteux.

D'après vous :
- Avec quelles structures des données ces deux fichiers seront remplacés ?

- En général,quelle est la structure des données la moins couteuse en mémoire et donc temps CPU le plus inférieur possible ?

2)
Comme vous dites la fonction DisplayConceptInfos [...] nous donne la liste des intents .

or pour chaque fichier xml alors je vais lire ce fichier c'est à dire pour chaque fichier xml on a une structure '_concepts'.

Au lieu de parcourir sur le nombre d fichier xml et faire une lecture de ce fichier et sauvegarder la liste de concepts dans'_concept' puis faire le traitement.

Je voulais lire une fois pour toute ces fichiers et sauvegarder la liste des concepts '_concepts' pour chaque fichier xml.

Et après parcourir liste par liste et faire le traitement.

Pour faire çà, est ce que la structure '_concept' est suffisante ou bien il faut la modifier par exemple on fait liste de liste ?

Que proposez vous ?

Merci.
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
2 nov. 2009 à 09:06
tu peux te faire une struct du genre

fileName
concepts

et jouer avec un tableau de cette structure pour stocker les données de ces n fichiers.

ainsi tout se passerait en mémoire, ce qui est rapide. De plus, les données en mémoire ne sont pas très volumineuses, j'ai bon espoir a penser que tes traitement seront très rapides ainsi

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
3 nov. 2009 à 00:48
Bonjour,

Quel est le syntaxe exacte de cette structure ?

Je n'arrive pas à comprendre votre idée.
S'il vous plait, Pouvez vous me détailler cette idée?

Merci.
0
Rejoignez-nous