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,


Oui.çà marche la chaine 'result' est sans espace à la fin.
Voici le code de chargement de la liste des 'intent' dans un tableau c'est chaque case de tableau contient les valeurs de 'intent' pour chaque 'extent' non nul et aussi le 'intent' doit non nul :
char * mstrndup(const char *str, size_t n)
{
    char *ret = malloc((n+1) * sizeof(char));

    if (!ret)
        exit(0);

    strncpy(ret, str, n); /* Copie n caractère de str dans n */
    ret[n] = 0; /* 0 == '\0' */
    return ret;
}

/** Teste le retour de realloc et quitte le programme si besoin */
void * xrealloc(void * prec, size_t len)
{
    void *ret = realloc(prec, len);
    if(!ret) /* Equivaut à if(ret == NULL) */
        exit(0);
    return ret;
}

// le chargement de tableau
char ** load_tab(CONCEPT* _concepts)
{
    
    REF* ref=NULL; 
int i,retsize = 0,p;
    char **ret = NULL,result[1024];
     
   


        for (p=0; p <_countCpt; p++)
{
          
ref = _concepts[p].intent;
if (_concepts[p].extent && ref) 
{
//strcpy(result,"\0");
result[0]='\0';

  while (ref)
  { 
    
if (ref->reference)
{
//if(strcmp(result,"\0"))
if(result[0]!='\0')
strcat(result," ");
strcat(result,ref->reference);

ref = ref->next;
}
  }
  printf("la chaine:::%s\n",result);
  ret = xrealloc(ret, (++retsize) * sizeof(char*)); /* On alloue une case de plus au tableau de string, puis on ajoute la chaine à la fin du tableau */
          ret[retsize-1] = mstrndup(result, strlen(result));// ? strl-1
}
      }
 
           
        ret = xrealloc(ret, (++retsize) * sizeof(char*)); /* On ajoute un dernier pointeur sur NULL pour savoir quand le tableau se termine */
        ret[retsize-1] = NULL;
       
    return ret;
}

int main()
{
char **rets = NULL;
lire_fichier("lattice1.lat.xml");

 rets = load_tab( _concepts);
 cleanup(); 
return 0;
}




Vous dites:
pas compris la question.

J'ai pensé que la fonction 'strcat(S1,S2)' ajoute la chaine S2 et un espace à S1. Mais,elle ajoute seulement S2 à S1 c'est une concaténation de S1 et S2.

tu ne mets plus cette partie ???

Pourquoi ? comment vous allez allouer le tableau et le remplir par 'result' ? On ne sait pas la taille de tableau car le nombre de concept réel dépend de fichier xml de plus on charge dans le tableau les 'intents' de concept qui ont un 'extent' non nul et 'intent' non nul.

-)Donc que proposez vous pour allouer ce tableau et le charger ?

-)Est ce que pouvez vous changer la structure '_concepts' ? de sorte on a tous les attributs 'intent' pour un 'extent' au leur de parcourir (boucle) un par un et les cumuler dans la chaine intermédiare 'resulut' car ceci prend de temps puisque ceci est fait pour chaque 'extent' de plus si on plusieurs 'intent' et plusieurs concepts.

Par exemple si on :
<Extent>
<Object_Ref>40787</Object_Ref>
<Object_Ref>14756</Object_Ref>
<Object_Ref>4771</Object_Ref>
<Object_Ref>4826</Object_Ref>
</Extent>

a
b
cc



-)Est ce que c'est possible d'avoir en changeant la structure de '_concept'
_concepts[i].intent="a b cc"
ou lieu d'avoir les trois séparés
_concepts[i].intent="a"
_concepts[i].intent="b"
_concepts[i].intent="cc"

Je souhaite que vous m'aidez et je n'oublierai pas vos aides.

Merci.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
Pas très malinque de vouloir stocker

"a b cc"

en effet, il faudra s'amuser à redécouper cette chaine pour séparer les valeurs a fin de comparaisons, etc.

bien plus utile d'avoir un tableau de ces valeurs

_concepts[i].intent[0]="a"
_concepts[i].intent[1]="b"
_concepts[i].intent[2]="cc"


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 ne comprends pas votre idée. Pouvez vous l'expliquer encore en détail ?
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
Et bien simplement de faire un tableau des valeurs là ou actuellement on a une liste chainée.

assez simple quand on y pense, si tu sais a combien de valeur on peut avoir a faire au maximum


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
D'accord, je vais lire un par un les 'intent' pour chaque 'extent' et les charger dans un tableau. c'est à dire pour chaque case de tableau contient toutes les valeurs de 'intent' d'un 'extent' donnée.
Voici ma solution:
char * mstrndup(const char *str, size_t n)
{
    char *ret = malloc((n+1) * sizeof(char));

    if (!ret)
        exit(0);

    strncpy(ret, str, n); /* Copie n caractère de str dans n */
    ret[n] = 0; /* 0 == '\0' */
    return ret;
}

/** Teste le retour de realloc et quitte le programme si besoin */
void * xrealloc(void * prec, size_t len)
{
    void *ret = realloc(prec, len);
    if(!ret) /* Equivaut à if(ret == NULL) */
        exit(0);
    return ret;
}

// le chargement de tableau
char ** load_tab(CONCEPT* _concepts)
{
    
    REF* ref=NULL; 
int i,retsize = 0,p;
    char **ret = NULL,result[1024];
     
   


        for (p=0; p <_countCpt; p++)
{
          
ref = _concepts[p].intent;
if (_concepts[p].extent && ref) 
{
//strcpy(result,"\0");
result[0]='\0';

  while (ref)
  { 
    
if (ref->reference)
{
//if(strcmp(result,"\0"))
if(result[0]!='\0')
strcat(result," ");
strcat(result,ref->reference);

ref = ref->next;
}
  }
  printf("la chaine:::%s\n",result);
  ret = xrealloc(ret, (++retsize) * sizeof(char*)); /* On alloue une case de plus au tableau de string, puis on ajoute la chaine à la fin du tableau */
          ret[retsize-1] = mstrndup(result, strlen(result));// ? strl-1
}
      }
 
           
        ret = xrealloc(ret, (++retsize) * sizeof(char*)); /* On ajoute un dernier pointeur sur NULL pour savoir quand le tableau se termine */
        ret[retsize-1] = NULL;
       
    return ret;
}

int main()
{
char **rets = NULL;
lire_fichier("lattice1.lat.xml");

 rets = load_tab( _concepts);
 cleanup(); 
return 0;
}



Que pensez vous pour cette solution?
Est ce que nous pouvons faire mieux c'est à dire l'optimiser?

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 chargé les 'intent' pour chaque 'extent' dans le tableau 'ret'.
chaque case de 'ret' contient tous les 'intents' d'un 'extent'.

J'ai deux tableaux 'tab' et 'ret'
chaque case de ces deux tableaux contient une chaine de caractère.
par exemple le contenu des cases de 'tab' respectivement :
case1 contient "nom prenom age"
case2 contient "nom age"
.....
prenom nom
nom age
nom prenom age
nom emploi
age emploi
prenom age emploi
nom age emploi
nom prenom emploi
nom prenom age emploi



le contenu des cases de 'ret' respectivement :
case1 contient "nom"
....
nom
prenom
age
emploi
age nom
nom age prenom
nom emploi
age emploi
nom prenom emploi


Le résultat souhaité sera stocké dans un tableau 'resultat' qui a deux cases dans ce cas car on ne sait pas sa taille on priori:

prenom age emploi
nom age emploi
nom prenom age emploi



Je voulais obtenir dans le tableaux ''resultat' les cases qui appartient 'tab' à n'appartient pas au 'ret' mais en tenant compte de deux choses:
- l'ordre des mots dans la chaine de caractère pas d'importance c'est dire :
"nom prenom age" de tableau 'tab' c'est la même que "nom age prenom" du tableau 'ret'
Ces deux chaines sont les mêmes et donc on ne met pas la chaine "nom prenom age" dans le tablaeu 'resultat'.

- Aussi, l'inclusion c'est à dire:
si j'ai une chaine de 'tab' inclut dans une chaine de 'ret' alors ces deux chaines sont égales.
par exemple:
"prenom nom" de tableau 'tab' c'est la même que "nom age prenom" du tableau 'ret'
Ces deux chaines sont les mêmes et donc on ne met pas la chaine "prenom nom" dans le tablaeu 'resultat'.

Je n'arrive pas à utiliser 'strcmp' ans ce cas pour faire la comparaison.
Je souhaite que vous m'aidez.

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

Je souhaite que vous m'aidez car je n'ai pas trouvé l'idée de cette comparaison.

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 propre code. Je voulais modifiez la solution ou lieu de faire *** rets(tableau de tableau) alors on fait **rets(un simple)tableau de chaine de caractères car je vais faire une seule comparaison entre deux tableaux.
Que proposez vous comme solution et modification à faire dans l'appel de fonction de comparaison et l'allocation de 'rets' et dans la fonction de comparaison de telle sorte que 'rets' soit un simple tableau de chaines de caractères ?


Voici l'appel de cette fonction:
char ***rets = NULL;
rets = malloc (nbre * sizeof(char**));
rets[0] = compare_files(tab_comb,nb_comb,tab_con,nb_con);

Voici la fonction de comparaison :
/** Compare deux fichiers er renvoie le résultat de la comparaison */

char ** compare_files(char **tab_comb,int nb_comb,char ***tab_con,int nb_con)
{
    
    
int i,a, retsize = 0,index,p;
    char **ret = NULL,result[1024];
int size1;
    
for(i=0;i<nb_comb;i++)
     {
  
            a = 0;
         
      for (p=0; p <nb_con; p++)
{
          
if (is_same(tab_comb[i], tab_con[0][p], 0))
                {
 
                    a = 1;
                    break;
                }
          
} 

       if (!a)
            {
                ret = xrealloc(ret, (++retsize) * sizeof(char*)); /* On alloue une case de plus au tableau de string, puis on ajoute la chaine à la fin du tableau */
              	ret[retsize-1] = mstrndup(tab_comb[i], strlen(tab_comb[i]));

            }
}   

           
        ret = xrealloc(ret, (++retsize) * sizeof(char*)); /* On ajoute un dernier pointeur sur NULL pour savoir quand le tableau se termine */
        ret[retsize-1] = NULL;

   

    return ret;
}



Je souhaite que vous m'aidez.

Merci.