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

Python Discussion :

Récupérer les infos contenues dans un fichier XML en gardant l'ordre de déclaration


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut Récupérer les infos contenues dans un fichier XML en gardant l'ordre de déclaration
    Bonjour, j'ai un fichier XML du type 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
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?>
    <!-- IMPORTANT : LA LIGNE CI-DESSUS NE DOIT JAMAIS ETRE OUBLIEE -->
     
    <!-- DECLARATION DU TYPE DE FICHIER DU POINT DE VUE DE BaNaMa -->
    <banama type="cont">
    <!-- Présentation rapide des logiciels -->
        <desc nivo="eleve prof">
    Texte description No1
        </desc>
     
    <!-- SpeedCrunch -->
        <log nom="SpeedCrunch" date="16/10/2008" nivo="eleve prof">
    Presentation de SpeedCrunch
        </log>
     
    <!-- Présentation rapide des logiciels -->
        <desc nivo="prof">
    Texte description No2
        </desc>
     
    <!-- Fprime -->
        <log nom="Fprime" date="28/2/2008" nivo="eleve">
    Presentation de Fprime
          </log>
    </banama>
    Je voudrais que Python m'analyse ce fichier en me renvoyant la liste suivante :
    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
    ana[0] = {'type': 'cont'}   # Pour la balise globale banama
    ana[1] = {'type': 'desc',
              'nivo' : 'eleve prof',
              'text' : 'Texte description No1'}
    ana[1] = {'type': 'log',
              'nivo' : 'eleve prof',
              'nom' : 'SpeedCrunch',
              'date' ; '16/10/2008',
              'text' : 'Presentation de SpeedCrunch'}
    ana[1] = {'type': 'desc',
              'nivo' : 'prof',
              'text' : 'Texte description No2'}
    ana[1] = {'type': 'log',
              'nivo' : 'eleve',
              'nom' : 'Fprime',
              'date' ; '28/2/2008',
              'text' : 'Presentation de Fprime'}
    Il est important que l'ordre soit respecté...

    Toute info. est la bienvenue.

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Je sais , je sais ... pour le problème que tu exposes, tout le monde fera d’abord une analyse syntaxique avec ElementTree ou quelque autre logiciel du même genre avant d’analyser le résultat du parsage pour en dériver ce que tu veux.

    Mais moi j’aime bien faire les choses par moi-même et surtout je ne connais suffisamment bien aucun logiciel de parsage pour faire ça. Donc voila mon petit machin, je me suis bien amusé.

    L’ordre des balises est respecté dans chacune des listes ana[x], mais il ne l’est par définition pas dans les dictionnaires contenus dans ces listes. J’ai supposé que tu ne parlais pas de cet ordre-ci dans mais de l’ordre des balises dans tes ana[0],ana[1],etc.

    D’ailleurs au passage, écrire ana[1] = blabla
    puis ana[1] = autre blabla etc , ce n’est pas compréhensible. J’ai donc supposé que les 0,1... devaient coder le niveau d’indentation et j’ai donc défini ana à ma façon. Si ce n’est pas ça, il fallait expliquer mieux.

    Ce n’est sans doute pas parfait. Si tu as des questions ou tu veux modifier , n’hésite pas.


    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
    import re
    from collections import defaultdict
     
    ana = defaultdict(list)
    patLine = re.compile(' (.+?=".+?)"')
     
    f = open('bana.txt')
    ch = f.read()
    f.close()
     
    balises = set(re.findall('^ *</(\w+)> *',ch,re.M))
    patGlob = re.compile('( *)<('+'|'.join(balises)+')(.*)\r?\n(?:(?:<!-- .+ -->)|(.*))\n')
     
    for mGlob in patGlob.finditer(ch):
        d = dict([ u.split('="') for u in patLine.findall(mGlob.group(3))])
        if mGlob.group(4):
            d['text'] = mGlob.group(4)
        if 'type' not in d:
            d['type'] = mGlob.group(2)
     
        ana[len(mGlob.group(1))//4].append(d)
     
    print 'Dictionaire "ana" de liste de dictionnaires :'
    for u in ana:
        print '\n\n   liste ana['+str(u)+'] :\n\n'+repr(ana[u])[1:-1].replace('}, ','}\n\n').replace(', ','\n')
    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
    Dictionaire "ana" de liste de dictionnaires :
     
     
       liste ana[0] :
     
    {'type': 'cont'}
     
     
       liste ana[1] :
     
    {'text': 'Texte description No1'
    'type': 'desc'
    'nivo': 'eleve prof'}
     
    {'date': '16/10/2008'
    'nom': 'SpeedCrunch'
    'type': 'log'
    'nivo': 'eleve prof'
    'text': 'Presentation de SpeedCrunch'}
     
    {'text': 'Texte description No2'
    'type': 'desc'
    'nivo': 'prof'}
     
    {'date': '28/2/2008'
    'nom': 'Fprime'
    'type': 'log'
    'nivo': 'eleve'
    'text': 'Presentation de Fprime'}

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Simplifié


    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
    import re
    from collections import defaultdict
     
    f = open('bana.txt')
    ch = f.read()
    f.close()
     
    ana = defaultdict(list)
    patLine = re.compile(' (.+?)="(.+?)"')
    balises = set(re.findall('^ *</(\w+)> *',ch,re.M))
     
    for mGlob in re.finditer('( *)<('+'|'.join(balises)+')(.*)\r?\n(?:(?:<!-- .+ -->)|(.*))\n',ch):
        d = dict(patLine.findall(mGlob.group(3)))
        if mGlob.group(4):
            d['text'] = mGlob.group(4)
        d.setdefault('type',mGlob.group(2))
     
        ana[len(mGlob.group(1))//4].append(d)
     
    print 'Dictionaire "ana" de liste de dictionnaires :'
    for u in ana:
        print '\n\n   liste ana['+str(u)+'] :\n\n'+repr(ana[u])[1:-1].replace('}, ','}\n\n').replace(', ','\n')

  4. #4
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Citation Envoyé par eyquem Voir le message
    Je sais , je sais ... pour le problème que tu exposes, tout le monde fera d’abord une analyse syntaxique avec ElementTree ou quelque autre logiciel du même genre avant d’analyser le résultat du parsage pour en dériver ce que tu veux.
    Ce type d'outil n'a pas l'air, il me semble, de gérer l'ordre suivant lequel ont été tapées les infos.

    Citation Envoyé par eyquem Voir le message
    L’ordre des balises est respecté dans chacune des listes ana[x], mais il ne l’est par définition pas dans les dictionnaires contenus dans ces listes. J’ai supposé que tu ne parlais pas de cet ordre-ci dans mais de l’ordre des balises dans tes ana[0],ana[1],etc.

    D’ailleurs au passage, écrire ana[1] = blabla
    puis ana[1] = autre blabla etc , ce n’est pas compréhensible. J’ai donc supposé que les 0,1... devaient coder le niveau d’indentation et j’ai donc défini ana à ma façon. Si ce n’est pas ça, il fallait expliquer mieux.
    Ne m'engeules pas... Plus sérieusement, je veux garder l'ordre d'écriture dans le fichier XML. C'est important car le fichier est un document et non une suite d'infos séparées.

    Merci.

  5. #5
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Voilà ce que j'ai fait comme modification.
    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
    import re
     
    f = open('ContenuSite_Test.xml')
    #f = open('bana.txt')
    ch = f.read()
    f.close()
     
    ana = []
    patLine = re.compile(' (.+?)="(.+?)"')
    balises = set(re.findall('^ *</(\w+)> *',ch,re.M))
     
    for mGlob in re.finditer('( *)<('+'|'.join(balises)+')(.*)\r?\n(?:(?:<!-- .+ -->)|(.*))\n',ch):
        d = dict(patLine.findall(mGlob.group(3)))
        if mGlob.group(4):
            d['text'] = mGlob.group(4)
        d.setdefault('type',mGlob.group(2))
     
        ana.append(d)
     
    for i in range(len(ana)):
        print '\n\tliste ana[' + str(i) + '] :\n'+str(ana[i])
    Le code ci-dessus me renvoie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    	liste ana[0] :
    {'type': 'cont'}
     
    	liste ana[1] :
    {'date': '1/5/2007', 'nom': 'DeadLine', 'type': 'log', 'nivo': 'eleve prof', 'text': 'Presentation de DeadLine'}
     
    	liste ana[2] :
    {'date': '16/10/2008', 'nom': 'SpeedCrunch', 'type': 'log', 'nivo': 'eleve prof', 'text': 'Presentation de SpeedCrunch'}
     
    	liste ana[3] :
    {'date': '28/2/2008', 'nom': 'Fprime', 'type': 'log', 'nivo': 'eleve', 'text': 'Presentation de Fprime'}
    C'est presque bon sauf qu'il me manque les noeuds de type desc contenu dans le fichier ContenuSite_Test.xml.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	<desc nivo="eleve prof">
    Texte description No1
    	</desc>
     
    	<desc nivo="prof">
    Texte description No2
    	</desc>

  6. #6
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Problème trouvé. En fait dans mon fichier, les balises fermées </desc> sont précédées d'une tabulation et non d'espaces.

    Solution à trouver. Comment peut-on remplacer la regex dans balises pour qu'elle prenne en compte une combinaison d'espaces et de tabulations à la suite dans un ordre quelconque ?

  7. #7
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Cela semble fonctionner même si je ne vois vraiment pas pourquoi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    balises = set(re.findall('^\t* *</(\w+)> *',ch,re.M))
    Encore une fois merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Lazarus] Récupérer une image contenue dans un fichier XML
    Par Tux74 dans le forum Lazarus
    Réponses: 1
    Dernier message: 13/10/2011, 23h14
  2. Récupérer l'info contenue dans les check box
    Par TopCao dans le forum MATLAB
    Réponses: 6
    Dernier message: 04/03/2010, 17h19
  3. Réponses: 4
    Dernier message: 27/01/2009, 18h14
  4. [XPath] Récupérer l'ID max dans un fichier XML
    Par Phach dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 28/07/2005, 13h57
  5. Réponses: 5
    Dernier message: 16/03/2005, 22h17

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