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

  1. #1
    Membre chevronné

    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
    Points : 1 752
    Points
    1 752
    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 extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    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 extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    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 chevronné

    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
    Points : 1 752
    Points
    1 752
    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 chevronné

    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
    Points : 1 752
    Points
    1 752
    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 chevronné

    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
    Points : 1 752
    Points
    1 752
    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 chevronné

    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
    Points : 1 752
    Points
    1 752
    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.

  8. #8
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    Je ne vois pas non plus pourquoi la RE '^\t* *</(\w+)> *' conviendrait. Elle n’attrapera que les balises fermantes précédées de un ou plusieurs ’\t’ , mais pas les autres balises fermantes.

    C’est tout simple, il faut metre un OU:
    balises = set(re.findall('^(\t| )* *</(\w+)> *',ch,re.M))

    Pour mettre ce OU , on est obligé d’entourer de parenthèses; ce faisant on crée un nouveau groupe. Pour l’éviter , il suffit d’ajouter ’?:’ après la première parenthèse:

    balises = set(re.findall('^(?:\t| )* *</(\w+)> *',ch,re.M))



    On peut penser que ce problème risque de survenir pour les balises ouvrantes aussi. Il vaut mieux améliorer de la même façon la RE dans finditer.

    Constatant que tu veux que ana soit une liste et non pas un dictionnaire et que donc les x dans ana[x] ne codent pas l’indentation de la balise ouvrante, mais sont simplement les indices dans la liste ana, il résulte qu’il n’y a aucun intérêt à garder la création du group(1) qui permettait d’écrire
    len(mGlob.group(1))//4

    Par conséquent, on peut éliminer la création du group(1) en mettant aussi ’?:’ dans la RE modifiée de finditer, ce qui donne

    re.finditer('(?:\t| )*<('+'|'.join(balises)+etc.......
    Au passage, je pense qu’il est bon d’ajouter un contrôle supplémentaire de la chaîne à détecter en ajoutant un ’^’ en tête de la RE, et pour cela il faut ajouter re.M à la fin.

    for mGlob in re.finditer('^(?:\t| )*<('+'|'.join(balises)+')(.*)\r?\n(?:(?:<!-- .+ -->)|(.*))\r?\n',ch,re.M):



    Mais le nombre et la nature des groupes détectés ne sont alors plus les mêmes, il faut diminuer de 1 les numéros de groupes précédemment employés.





    Encore une petite amélioration: faire l’affichage au fur et à mesure qu’on a d sous la main, et pour avoir l’indice utiliser enumerate...

    et hop !

    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
    import re
    f = open('ContenuSite_Test.xml')
    ch = f.read()
    f.close()
     
    ana = []
    patLine = re.compile(' (.+?)="(.+?)"')
     
    balises = set(re.findall('^(?:\t| )*</(\w+)> *',ch,re.M))
    print 'Liste "ana" de dictionnaires :'
    for i,mGlob in enumerate(re.finditer('^(?:\t| )*<('+'|'.join(balises)+')(.*)\r?\n(?:(?:<!-- .+ -->)|(.*))\n',ch,re.M)):
        d = dict(patLine.findall(mGlob.group(2)))
        if mGlob.group(3):
            d['text'] = mGlob.group(3)
        d.setdefault('type',mGlob.group(1))
        ana.append(d)
        print '\n\tdictionnaire ana[' + str(i) + '] :\n'+str(d)
    J’ai appris dans ton code qu’on pouvait faire str(liste) et donc str(dictionnaire) etc. Jusqu’à present j’utilisais repr().

    repr() reste indispensable pour afficher une chaîne de façon brute sans faire jouer les tabulations,newlines, etc.



    Eh, t’as vu le nombre de lignes auxquelles on arrive ?
    Et tu connaissais le coup d'un enumerate sur finditer ? Quand j'ai découvert ça, ça m’a bien simplifié les choses (avant ton pb).
    Python, c’est DiiiiiiiNGuE !



    – Je ne t’ai pas engueulé. Même pas rouspété en l’occurence. J’ai énoncé une remarque vraie. C’est vrai que ces ambigüités dans les messages m’étonnent toujours, comme si les rédacteurs ne s’apercevaient pas qu’il y a quelque chose de pas clair.
    L’accumulation d’ambigüités finit par m’agacer, c’est vrai. Ça peut me mener à rouspéter ou même plus. Mais pas là.
    La prochaine fois je mettrai des smiles.

    Bon vekende.


    PS :
    Normalement, quand Python lit un fichier , quelles que soient les newlines, il les transforme en ’\n’, sauf si on spécifie (je ne sais pas comment) qu’il ne faut pas qu’il le fasse.
    Pour prévenir le coup dans n’importe quelle situation, j’ai mis ’\r?’ dans les RE.
    Je l’avais oublié dans la RE de finditer.

  9. #9
    Membre chevronné

    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
    Points : 1 752
    Points
    1 752
    Par défaut
    Citation Envoyé par eyquem Voir le message
    C’est tout simple, il faut mettre un OU:
    balises = set(re.findall('^(\t| )* *</(\w+)> *',ch,re.M))

    Pour mettre ce OU , on est obligé d’entourer de parenthèses; ce faisant on crée un nouveau groupe. Pour l’éviter , il suffit d’ajouter ’?:’ après la première parenthèse:

    balises = set(re.findall('^(?:\t| )* *</(\w+)> *',ch,re.M))

    On peut penser que ce problème risque de survenir pour les balises ouvrantes aussi. Il vaut mieux améliorer de la même façon la RE dans finditer.
    Merci beaucoup, cela marche sans problème. Merci aussi pour les améliorations. Je vais tester cela sur d'autre types de fichiers XML : en fait je veux aussi lire le contenu de fichier fait par un logiciel comme GeoGebra.

    Citation Envoyé par eyquem Voir le message
    Eh, t’as vu le nombre de lignes auxquelles on arrive ?
    Le nombre de lignes auquel tu arrives. Bravo pour cet exploit.

    Citation Envoyé par eyquem Voir le message
    Et tu connaissais le coup d'un enumerate sur finditer ? Quand j'ai découvert ça, ça m’a bien simplifié les choses (avant ton pb).
    Je t'avouerais que je suis un peu dépassé... Quelle est l'autre écriture que tu utilisais avant?

    Citation Envoyé par eyquem Voir le message
    – Je ne t’ai pas engueulé. Même pas rouspété en l’occurence. J’ai énoncé une remarque vraie. C’est vrai que ces ambigüités dans les messages m’étonnent toujours, comme si les rédacteurs ne s’apercevaient pas qu’il y a quelque chose de pas clair.
    L’accumulation d’ambigüités finit par m’agacer, c’est vrai.
    Pas de souci, tu as raison. Moi aussi quelques fois cela m'énerve un peu.

    Encore une fois, mille mercis pour la célérité de tes réponses.

  10. #10
    Membre chevronné

    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
    Points : 1 752
    Points
    1 752
    Par défaut
    Ca se complique un peu car je vais devoir adapter la méthode ci-dessus à un autre cas de fichier que voici :
    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="utf-8"?>
    <geogebra format="3.2">
    	<gui>
    		<show algebraView="true" spreadsheetView="false"/>
    		<font  size="12"/>
    	</gui>
    	<kernel>
    		<continuous val="false"/>
    		<decimals val="2"/>
    	</kernel>
    	<construction title="" author="" date="">
    		<element type="point" label="A">
    			<layer val="0"/>
    			<labelMode val="0"/>
    			<coords x="-1.3" y="2.94" z="1.0"/>
    			<pointSize val="3"/>
    		</element>
    		<element type="point" label="B">
    			<labelMode val="0"/>
    			<animation step="0.1" speed="1" type="0" playing="false"/>
    			<coords x="2.02" y="3.24" z="1.0"/>
    			<pointSize val="3"/>
    		</element>
    	</construction>
    </geogebra>
    Le cahier des charges (si on peut dire cela quand on est amateur) est presque le même. Je voudrais avoir la dictionnaire suivant après analyse :
    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
    # ana est un dictionnaire.
     
    ana['gui'] = {'contenu' : {'show': {'algebraView': "true", 'spreadsheetView': "false"},
                               'font': {'size': "12"}}}
     
    ana['kernel'] = {'contenu' : {'continuous': {val: "false"},
                                  'decimals': {val: "2"}}}
     
    ana['construction'] = {'title': "",
                           'author': "",
                           'date': "",
                           'contenu' : listElements}
     
    # On doit avoir :
    listElements[0] = {'type': "point",
                       'label': "A",
                       'contenu' : {'layer': {'val': "0"},
                                    'labelMode': {'val': "0"},
                                    'coords': {'x': "-1.3", 'y':"2.94", 'z':"1.0"}}
                                    'pointSize': {'val': "3"}}
     
    listElements[1] = {'type': "point",
                       'label': "B",
                       'contenu' : {'labelMode': {'val': "0"},
                                    'animation': {'step': "0.1", 'speed': "1", 'type': "0", 'playing': "false"},
                                    'coords': {'x': "2.02", 'y':"3.24", 'z':"1.0"}}
                                    'pointSize': {'val': "3"}}
    Quelqu'un a-t-il une idée ? Désolé je n'ai pas trouvé une question plus simple.

  11. #11
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    Je m’y attendais à ce que les besoins n’en restent pas au précédent fichier.
    On va se retrouver à écrire un parser juste pour avoir les noeuds dans leur ordre de déclaration.

    J’ai regardé à peine un petit peu mais il me semble que ça va devenir trop complexe avec des regex d’un seule tenant. Il va falloir introduire des if et autres joyeusetés.

    Je pense qu’il va devenir plus judicieux si le mouvement de complexification doit se poursuivre de:
    - parser le texte avec un parser disponible déjà fait
    - traiter son résultat, c’est à dire les noeuds organisés hiérarchiquement pour les changer d’ordre et les mettre en un ordre “chronologique“

    Le challenge du “tout par soi-même“ m’intéresse, c’est marrant. Mais je n’ai pas trop le temps et je ne suis pas sûr qu’on arrivera au bout.

    Je continue de regarder un peu.

  12. #12
    Membre éprouvé

    Profil pro
    Inscrit en
    Août 2004
    Messages
    723
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 723
    Points : 923
    Points
    923
    Par défaut
    Dans cElementTree, il y a iterparse qui permet de lire dans l'ordre chronologique
    http://effbot.org/zone/element-iterparse.htm

  13. #13
    Membre chevronné

    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
    Points : 1 752
    Points
    1 752
    Par défaut
    Hum, miam, miam... Plutôt que te donner la réponse très spécifique à mon problème très personnel, je donne juste le snippet suivant (obtenu directement d'après les sources ci-desssous) qui donne la base pour créer mon dico. :
    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
    #!/usr/bin/env python
    #coding=utf-8
    # Sources :
    #        http://effbot.org/zone/element-iterparse.htm
    #        http://effbot.org/zone/element.htm
    import xml.etree.cElementTree as ET
    source = 'geogebra.xml'
    # get an iterable
    context = ET.iterparse(source, events=("start", "end"))
    # turn it into an iterator
    context = iter(context)
    # get the root element
    event, root = context.next()
    for event, elem in context:
        print (str(event), str(elem.tag), str(elem.items()))
    Merci à tous les deux !

  14. #14
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    Un copié-collé de ton snipet , et lancé donne l’erreur suivante

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Traceback (most recent call last):
      File "E:/Python/Essais Python/zsnipet.py", line 13, in <module>
        event, root = context.next()
      File "<string>", line 64, in __iter__
    SyntaxError: mismatched tag: line 6, column 3



    De mon coté j’ai pondu ça
    Il a fallu bouleverser complétement l’algorithme et les regex


    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
    import re
    f = open('bana2.txt')
    chfich = f.read()
    f.close()
     
    ana = []
    patLine = re.compile(' (.+?)="(.+?)"')
    print 'balises =',re.findall('^(?:\t| )*</(\w+)> *',ch,re.M)
    balises = set(re.findall('^(?:\t| )*</(\w+)> *',ch,re.M))
     
    print
    print 'Liste "ana" de dictionnaires :'
     
    RE = '^(?:\t| )*<('+'|'.join(balises)+')(.*)>\r?\n'\
         +'(^(?:(.*)\r?\n)*)?'\
         +'^(?:\t| )*</\\1>'
     
    dkt = 0
     
    patln = re.compile('^(?:\t| )*<([^ .]+)(.+)?/?>')
     
    def treat(ch):
        print '\n###########################################################################'
        d = {}
        for m in re.finditer(RE,ch,re.M):
     
            if m.group(2):
                d[m.group(1)] = dict(patLine.findall(m.group(2)))
     
            if m.group(3):
                if re.findall('^(?:\t| )*</(\w+)> *',m.group(3),re.M)==[]:
                    dcont = {}
                    for ln in m.group(3).splitlines():
                        mln = patln.match(ln)
                        dcont[mln.group(1)] = dict(re.findall(' (.+?)="(.+?)"',mln.group(2)))
                    if d.has_key(m.group(1)):
                        d.update((('contenu',dcont),))
                    else:
                        d[m.group(1)] = dict((('contenu',dcont),))
                else:
                    if d.has_key(m.group(1)):
                        d.update(( ('contenu',treat(m.group(3))), ))
                    else:
                        d[m.group(1)] = dict((('contenu',treat(m.group(3))),))
     
     
            if m.group(3):
                d['contenu'] = m.group(3)
                treat(m.group(3))
     
            print 'm.group(1) =',repr(m.group(1))
            print
            print 'd[',m.group(1),'] ='
            for k in d:
                print k,':',repr(d[k])
                print '==================================='
        return d
     
    treat(chfich)

    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
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
     
    balises = ['gui', 'kernel', 'element', 'element', 'construction', 'geogebra']
     
    Liste "ana" de dictionnaires :
     
    ###########################################################################
     
    ###########################################################################
     
    ###########################################################################
    m.group(1) = 'gui'
     
    d[ gui ] =
    contenu : '\t\t<show algebraView="true" spreadsheetView="false">\n\t\t<font  size="12"/>\n'
    ===================================
    gui : {'contenu': {'font': {' size': '12'}, 'show': {'algebraView': 'true', 'spreadsheetView': 'false'}}}
    ===================================
     
    ###########################################################################
    m.group(1) = 'kernel'
     
    d[ kernel ] =
    contenu : '\t\t<continuous val="false"/>\n\t\t<decimals val="2"/>\n'
    ===================================
    gui : {'contenu': {'font': {' size': '12'}, 'show': {'algebraView': 'true', 'spreadsheetView': 'false'}}}
    ===================================
    kernel : {'contenu': {'continuous': {'val': 'false'}, 'decimals': {'val': '2'}}}
    ===================================
     
    ###########################################################################
     
    ###########################################################################
     
    ###########################################################################
    m.group(1) = 'element'
     
    d[ element ] =
    contenu : '\t\t\t<layer val="0"/>\n\t\t\t<labelMode val="0"/>\n\t\t\t<coords x="-1.3" y="2.94" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n\t\t</element>\n\t\t<element type="point" label="B">\n\t\t\t<labelMode val="0"/>\n\t\t\t<animation step="0.1" speed="1" type="0" playing="false"/>\n\t\t\t<coords x="2.02" y="3.24" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n'
    ===================================
    element : {'type': 'point', 'label': 'A'}
    ===================================
     
    ###########################################################################
     
    ###########################################################################
     
    ###########################################################################
    m.group(1) = 'element'
     
    d[ element ] =
    contenu : '\t\t\t<layer val="0"/>\n\t\t\t<labelMode val="0"/>\n\t\t\t<coords x="-1.3" y="2.94" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n\t\t</element>\n\t\t<element type="point" label="B">\n\t\t\t<labelMode val="0"/>\n\t\t\t<animation step="0.1" speed="1" type="0" playing="false"/>\n\t\t\t<coords x="2.02" y="3.24" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n'
    ===================================
    element : {'type': 'point', 'label': 'A'}
    ===================================
    m.group(1) = 'construction'
     
    d[ construction ] =
    contenu : '\t\t<element type="point" label="A">\n\t\t\t<layer val="0"/>\n\t\t\t<labelMode val="0"/>\n\t\t\t<coords x="-1.3" y="2.94" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n\t\t</element>\n\t\t<element type="point" label="B">\n\t\t\t<labelMode val="0"/>\n\t\t\t<animation step="0.1" speed="1" type="0" playing="false"/>\n\t\t\t<coords x="2.02" y="3.24" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n\t\t</element>\n'
    ===================================
    gui : {'contenu': {'font': {' size': '12'}, 'show': {'algebraView': 'true', 'spreadsheetView': 'false'}}}
    ===================================
    construction : {'title': '" author='}
    ===================================
    kernel : {'contenu': {'continuous': {'val': 'false'}, 'decimals': {'val': '2'}}}
    ===================================
     
    ###########################################################################
     
    ###########################################################################
    m.group(1) = 'gui'
     
    d[ gui ] =
    contenu : '\t\t<show algebraView="true" spreadsheetView="false">\n\t\t<font  size="12"/>\n'
    ===================================
    gui : {'contenu': {'font': {' size': '12'}, 'show': {'algebraView': 'true', 'spreadsheetView': 'false'}}}
    ===================================
     
    ###########################################################################
    m.group(1) = 'kernel'
     
    d[ kernel ] =
    contenu : '\t\t<continuous val="false"/>\n\t\t<decimals val="2"/>\n'
    ===================================
    gui : {'contenu': {'font': {' size': '12'}, 'show': {'algebraView': 'true', 'spreadsheetView': 'false'}}}
    ===================================
    kernel : {'contenu': {'continuous': {'val': 'false'}, 'decimals': {'val': '2'}}}
    ===================================
     
    ###########################################################################
     
    ###########################################################################
     
    ###########################################################################
    m.group(1) = 'element'
     
    d[ element ] =
    contenu : '\t\t\t<layer val="0"/>\n\t\t\t<labelMode val="0"/>\n\t\t\t<coords x="-1.3" y="2.94" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n\t\t</element>\n\t\t<element type="point" label="B">\n\t\t\t<labelMode val="0"/>\n\t\t\t<animation step="0.1" speed="1" type="0" playing="false"/>\n\t\t\t<coords x="2.02" y="3.24" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n'
    ===================================
    element : {'type': 'point', 'label': 'A'}
    ===================================
     
    ###########################################################################
     
    ###########################################################################
     
    ###########################################################################
    m.group(1) = 'element'
     
    d[ element ] =
    contenu : '\t\t\t<layer val="0"/>\n\t\t\t<labelMode val="0"/>\n\t\t\t<coords x="-1.3" y="2.94" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n\t\t</element>\n\t\t<element type="point" label="B">\n\t\t\t<labelMode val="0"/>\n\t\t\t<animation step="0.1" speed="1" type="0" playing="false"/>\n\t\t\t<coords x="2.02" y="3.24" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n'
    ===================================
    element : {'type': 'point', 'label': 'A'}
    ===================================
    m.group(1) = 'construction'
     
    d[ construction ] =
    contenu : '\t\t<element type="point" label="A">\n\t\t\t<layer val="0"/>\n\t\t\t<labelMode val="0"/>\n\t\t\t<coords x="-1.3" y="2.94" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n\t\t</element>\n\t\t<element type="point" label="B">\n\t\t\t<labelMode val="0"/>\n\t\t\t<animation step="0.1" speed="1" type="0" playing="false"/>\n\t\t\t<coords x="2.02" y="3.24" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n\t\t</element>\n'
    ===================================
    gui : {'contenu': {'font': {' size': '12'}, 'show': {'algebraView': 'true', 'spreadsheetView': 'false'}}}
    ===================================
    construction : {'title': '" author='}
    ===================================
    kernel : {'contenu': {'continuous': {'val': 'false'}, 'decimals': {'val': '2'}}}
    ===================================
    m.group(1) = 'geogebra'
     
    d[ geogebra ] =
    geogebra : {'format': '3.2'}
    ===================================
    contenu : '\t<gui>\n\t\t<show algebraView="true" spreadsheetView="false">\n\t\t<font  size="12"/>\n\t</gui>\n\t<kernel>\n\t\t<continuous val="false"/>\n\t\t<decimals val="2"/>\n\t</kernel>\n\t<construction title="" author="" date="">\n\t\t<element type="point" label="A">\n\t\t\t<layer val="0"/>\n\t\t\t<labelMode val="0"/>\n\t\t\t<coords x="-1.3" y="2.94" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n\t\t</element>\n\t\t<element type="point" label="B">\n\t\t\t<labelMode val="0"/>\n\t\t\t<animation step="0.1" speed="1" type="0" playing="false"/>\n\t\t\t<coords x="2.02" y="3.24" z="1.0"/>\n\t\t\t<pointSize val="3"/>\n\t\t</element>\n\t</construction>\n'
    ===================================
    >>>
    Ça tourne sans erreur.
    Je me demande un peu comment je suis arrivé à ça.

    À cette heure de la nuit, je ne comprends plus très bien ce que c’est censé donner.
    Je te le laisse, vois ce que tu peux en faire.

    Je ne peux pas y revenir de quelques jours.

  15. #15
    Membre chevronné

    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
    Points : 1 752
    Points
    1 752
    Par défaut
    L'erreur venait de mon code XML qui contenait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <show algebraView="true" spreadsheetView="false">
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <show algebraView="true" spreadsheetView="false"/>
    Il manquait un / pour fermer la balise. J'ai corrigé dans le post ci-dessus.

    Sinon merci pour ton code mais là j'avoue que cela devient trop compliqué pour moi.

  16. #16
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    Merci pour la correction. Je regarderai avec ce snipet plus tard.





    Je réviserai aussi mon code plus tard. Je l’ai écrit à la va-vite ==> il est très mal foutu.

    Il y a des redondances et par contre les contenus sont mal traités et ne sont pas enregistrés correctement.

    Tu as dû remarquer qu’il y a une fonction récursive, d’où la difficulté pour moi parce que je ne suis pas habitué à ce genre de fonctions.

    Mais c’est plus facile que je ne pensais et on arrivera au bout. Reste à savoir si ça présentera un intérêt particulier de ne pas utiliser ton snipet. Parce que je pense qu’en fait ton snipet ne fait que fournir des éléments que des regex dans mon code attraperont tout aussi bien.

    Salut

  17. #17
    Membre chevronné

    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
    Points : 1 752
    Points
    1 752
    Par défaut
    L'intérêt du snippet est qu'il gère aussi les erreurs du fichier XML.

    Sinon pour le côté récursif, j'aurais utilisé un schéma du type suivant :
    1. Repérer une balise, disons que son nom est newBalise.
    2. Regarder si newBalise est auto-fermante, ie du type <newBalise ... />. Si c'est le cas, on ajoute la balise avec ses infos complémentaires et un texte vide pour la clé 'contenu' dans une liste de dictionnaires, laquelle sera renvoyée par la fonction.
    3. On cherche le texte entre <newBalise> et </newBalise> pour le traiter de façon récursive. Ce traitement sera la valeur de la clé 'contenu'.


    En espérant avoir été clair.

  18. #18
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut @ rambc
    Voilà ce à quoi je suis arrivé après avoir repris mon code précédent. C’était un peu n’importe quoi ce précédent code.




    J’ai visé plus large que le code XML que tu as donné en exemple:
    j’ai envisagé la possibilité qu’il puisse ne pas y avoir qu’un seul type d’éléments dans un éléments plein, c’est à dire qu’il puisse y avoir des élements vides et des élements pleins en même temps. De plus j’ai envisagé qu’ils puissent être mélangés, et non pas séparés en deux temps (d’abord des éléments pleins puis des éléments vides, ou l’inverse).

    J’emploie les expressions éléments vides et éléments pleins en essayant de suivre les spécifications officielles du XML.

    Un élément plein est un contenu comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
       <layer val="0"/>
       <labelMode val="0"/>
       <coords x="-1.3" y="2.94" z="1.0"/>
       <pointSize val="3"/>
    entouré d’une balise ouvrante <element type="point" label="A"> (celle-ci contenant des attributs)
    et d’une balise fermante </element>

    Un élément vide est par exemple
    <show algebraView="true" spreadsheetView="false"/>
    NB : en toute rigueur, on devrait dire balise d’élément vide.





    Le “cahier des charges“ que tu as présenté s’appliquant à un exemple plus étroit que le cas général que je viens de dire, je ne savais pas ce que tu attendrais dans un cas plus large. Aussi ai-je décidé de répartir dans trois rubriques les informations de chaque éléments: dictionnaire attributs, dictionnaire éléments vides et dictionnaire éléments pleins.

    Je crois que ça correspond à l’essentiel de ce que tu veux: enregistrer chaque élément comme un item de dictionnaire, chaque item contenant la liste des éléments pleins enfants dans l’ordre d’apparition dans le code XML traité.

    Par contre les éléments vides se trouvent en désordre dans chaque dictionnaire éléments vides. En Python 3, l’ordre pourrait être conservé puisque Python 3 a introduit les dictionnaires ordonnés.

    Le résultat de mon code ne rend pas non plus compte de l’ordre dans lequel se succèdent des éléments pleins et des éléments vides mélangés.

    Je ne me suis pas lancé dans le codage pour obtenir cette information sans savoir si cela t’intéresse vraiment. Ce ne serait pas dur à ajouter je pense.






    Le noyau du code est une fonction récursive captant les informations et les enregistrant comme items de dictionnaires et dans des listes. Après coup, je trouve que c’est beaucoup plus simple que je prévoyais, mais ça m’a donné pas mal de fil à retordre pour y arriver.

    Les chaînes '<TE><TE --aucun--="TE><TE est un code source XML.">\n' et '\n</TE><TE>\n' que j’ajoute à la fin et au début du texte brut sont destinées à simplifier le démarrage de la procédure récursive et à éviter des tests de vérification fastidieux qui seraient sinon nécessaires.

    Le code est rébarbatif au premier coup d’œil mais ce n’est qu’une apparence: il est en fait assez simple et seulement rendu plus touffu parce que j’ai ajouté quelques instructions pour faire des vérifications des lignes du code XML, en fonction des spécifications que j’ai comprises concernant les attributs, les commentaires, etc.






    Les mauvaises lignes détectées par ces instructions sont enregistrés dans un dictionnaire “badies“, elles ne sont donc pas dans “ana“.

    Comme tu l’as évoqué, ton snipet fait cette vérification, il n’était donc pas indispensable que je réinvente la roue, ou plutôt une roulette.

    Mais je me suis d’abord concentré sur la fonction récursive sans vouloir utiliser le snipet, puis je me suis amusé à ajouter du code vérifiant le texte XML pour voir ce que ça implique.

    Maintenant il faudrait qu’on regarde ce qu’apporte ton snipet. Je regarderai un peu plus tard.





    D’une façon globale, je me demande si ça vaut vraiment le coup, en dehors de l’amusement et de l’auto-formation, de construire par soi-même un code alors que iterparse de ElementTree (tuyau de oiffrig, message #12) semble faire le même boulot. Il faudrait voir aussi de ce coté.

    Et aussi: as-tu toujours besoin d’un tel programme ?


    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
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    suivi = 'non'
    # donner la valeur 'oui' a suivi
    # pour afficher un suivi du deroulement
    # au cours de l'execution
     
    import re
    from collections import defaultdict
     
    def treat(ch,idy):
     
        #=================================================================
        if suivi=='oui':
            global txtecran
            if len(ch)<53:
                txtecran += '\n -*- CH EN ENTREE :\n'+repr(ch)
            else:
                txtecran += '\n -*- CH EN ENTREE :\n'+repr(ch[0:26]+min(8,(len(ch)-52))*'.'+ch[-26:])
        global nbalise,listElements
        prec = 0
        other = ''
        badlines = []
     
        #=== Traitement des elements pleins ==============================
        for mplein in patPleins.finditer(ch):
     
            name = mplein.group(1)
            if mplein.group(1) in nbalise:
                name += '_'+str(nbalise[mplein.group(1)])
                nbalise[mplein.group(1)] = nbalise[mplein.group(1)] + 1
            if suivi=='oui':
                txtecran += '\n\n\n ~*~ NOM DE BALISE : ' + name
     
            if not patAttributs.match(mplein.group(2)):
                badlines.append(('    '+repr(mplein.group(2)),"    ==> Cette chaine n'est pas une chaine d’attributs conforme."))
                if suivi=='oui':
                    txtecran += '\n  ' + repr(mplein.group(2))+"\n  ==> Cette chaine n'est pas une chaine d’attributs conforme."
     
            other += ch[prec:mplein.start()]
            prec = mplein.end()
     
            ana[name] = {'attributs':dict(patAtt.findall(mplein.group(2)))}
            elv,bad = treat(mplein.group(3),name)
            badlines.extend(bad)
            if badlines:
                badies[name] = badlines
            badlines = []
            ana[name]['elements_vides'] = elv
            listElements[idy].append(name)
            ana[name]['elements_pleins'] = "listElements['"+name+"']"
     
     
        #=================================================================
        other += ch[prec:]
        if suivi=='oui':
            if other:
                txtecran += "\n ~*~ LIGNES D'ELEMENTS VIDES dans la chaine CH EN ENTREE :"+repr(ch[0:18]+'...etc')\
                            + '\n' + '\n'.join([repr(u) for u in other.splitlines()])
            else:
                txtecran += "\n ~*~ Pas de LIGNES D'ELEMENTS VIDES dans la chaine CH EN ENTREE :"+repr(ch[0:18]+'...etc')
        dvides = {}
        badvides = []
     
        #=== Traitement des elements vides ================================
        for elvide in other.splitlines():
            mvide = patVides.match(elvide) # patVides = re.compile('(?:\t| )*<(?!/)([^ .]+)(.+?)?(/?>)\Z')
            if not mvide:
                if patComment.match(elvide):
                    if '--' not in patComment.match(elvide).group():
                        pass
                    else:
                        badvides.append('    '+(repr(elvide),"    ==> Ligne non conforme (censee etre un element vide)."))
                        if suivi=='oui':
                            txtecran += '\n  '+elvide+"\n  Ligne non conforme (censee etre un element vide)."
                else:
                    badvides.append(('    '+repr(elvide),"    ==> Ligne non conforme (censee etre un element vide)."))
                    if suivi=='oui':
                        txtecran += '\n  '+elvide+"\n  Ligne non conforme (censee etre un element vide)."
            elif patCom.match(elvide)==None:
                if mvide.group(2)!=None:
                    if mvide.group(2)[0:2]=='  ':
                        # group(2) est la chaîne des attributs
                        badvides.append(('    '+repr(elvide),"    ==> Un seul blanc doit suivre le nom."))
                        if suivi=='oui':
                            txtecran += '\n  '+repr(elvide)+"\n  Un seul blanc doit suivre le nom."
     
                    if mvide.group(2)!='' and patAttributs.match(mvide.group(2))==None:
                        # group(2) est la chaîne des attributs
                        badvides.append(('    '+repr(mvide.group(2)),"    ==> Cette chaine n'est pas une chaine d'attributs conforme."))
                        if suivi=='oui':
                            txtecran += '\n  '+repr(mvide.group(2))+"\n  Cette chaine n'est pas une chaine d'attributs conforme."
     
                    if mvide.group(3)!='/>' and mvide.group(1) not in baliz:
                        # group(3) est le bout de l'élément vide: ’/>’.
                        badvides.append(('    '+repr(elvide),"    ==> Il manque '/>' en bout de ligne."))
                        if suivi=='oui':
                            txtecran += '\n  '+repr(elvide)+"\n  Il manque '/>' en bout de ligne.)"
     
                    dvides[mvide.group(1)] = dict(re.findall(' (.+?)="(.+?)"',mvide.group(2)))
     
                else:
                    badvides.append(('    '+repr(elvide),"    ==> Cette ligne semble ne pas etre du tout conforme"))
                    if suivi=='oui':
                        txtecran += '\n  '+repr(elvide)+"\n  Cette ligne semble ne pas etre du tout conforme"
     
        if suivi=='oui':
            if dvides:
                txtecran += '\n ~*~ ELEMENTS_VIDES ='
                for k in dvides:
                    txtecran += '\n'+repr(k)+' : '+repr(dvides[k])
            else:
                txtecran += '\n ~*~ ELEMENTS_VIDES = {}'
            txtecran += '\n----- fin de '+repr(ch[0:12])+' -----\n'
     
        return dvides,badvides
     
     
    def aff(ref):
        x = "\nana['"+ref+"'] = {"
        x += '\n\nattributs       : ' + str(ana[ref]['attributs']) + ' ,'
        x += ('\n'+18*' ').join(('\n\nelements_vides  : '+repr(ana[ref]['elements_vides'])).replace('},','} ,},').split('},')) + ' ,'
        x += '\n\nelements_pleins : '+ ana[ref]['elements_pleins']+' = '+str(listElements[ref])+'    }'
     
        if ref in badies:
            x += '\n\n\nBAD LINES de '+ref+' :'
            for u,v in badies[ref]:
                x += '\n'+u+'\n'+v
     
        x += '\n\n----------------------------------------------------------------'
     
        for u in listElements[ref]:
            x += aff(u)
     
        return x
     
     
    #====================================================================================================
     
     
    f = open('bana2.txt')
    while 1:
        x = f.readline()
        if not re.match('^<\?.*?\?>',x):
            break
    chf = '<TE><TE --aucun--="TE><TE est un code source XML.">\n' + x + f.read() + '\n</TE><TE>\n'
    f.close()
     
    baliz   = re.findall('^</(?!TE><TE)([^ .]+?)>\r?\n',chf,re.M)
    balises = re.findall('^(?:\t| )*</([^ .]+?)>\r?\n',chf,re.M)
    setbalises = set(balises)
    print 'noms des balises : '+str([h for h in setbalises if h!='TE><TE'])[1:-1]
    balises_repetees = [u for u in setbalises if balises.count(u)>1]
    nbalise = {}.fromkeys(balises_repetees,1)
    print 'nbalise = '+str(nbalise)+'\n'
    del balises, balises_repetees
     
    patAtt       = re.compile(' ([^ ]+?)="([^"]+?)"')
    patAttributs = re.compile('( [^ ]+?="[^"]*?")*$')
    patPleins    = re.compile('(?:\t| )*<('+'|'.join(setbalises)+')(.*)>\n'\
                              '((?:^(?:\t| )*.*\n)*?)'\
                              '^(?:\t| )*(</\\1>)\n',re.M)
    patVides     = re.compile('(?:\t| )*<(?!/)([^ ]+)(.+?)?(/?>)\Z')
    patComment   = re.compile('(?:\t| )*<!--(?!-)(.*?)(?<!-)-->')
    patCom       = re.compile('(?:\t| )*<!--(?!-)')
     
    txtecran = ''
    listElements = defaultdict(list)
    ana,badies = {},{}
     
    dv,b = treat(chf,'TE><TE')
    if b:
        ana['TE><TE']['bad_lines'] = b
    ana['TE><TE']['elements_vides'] = dv
    ana['TE><TE']['elements_pleins'] = "listElements['TE><TE']"
    listElements['TE><TE'].remove('TE><TE')
     
    print txtecran
    print '\n\n\n================================================================\n'
    print aff('TE><TE')

    En faisant tourner ce code sur le texte ci-dssous:

    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
    <?xml version="1.0" encoding="utf-8"?>
    <? Ceci est une instruction de traitement ?>
    <? Instruction de traitement numero 2?>
    <? Troisieme instruction de traitement   ?>
    <geogebra format="3.2">
    	<kernel bidon="nimportkoi">
    		<seau pour="la plage"/>
    		<cuvette type="plastique"/>
    		<region gobi="desert" serenity="lune"/>
    	</kernel>
    	<gui>
    		<show algebraView="true" spreadsheetView="false"/>
    		<font size="12">
    	</gui>
    	<kernel>
    		<continuous    val="false"/>
    		<!-- Ceci est un commentaire -->
    		<!--      Ceci est un commentaire -->
    		<decimals val="2"/>
    	</kernel>
    	<jhkgkwjhgdf879769444>
    	<construction title="" author="" date="">
    		<tagada color="red" shade="metallic" effect="riples"/>
    		<element type="point" label="A">
    			<layer val="0"/>
    			<labelMode val="0"/>
    			<-!- Commentaire foireux -->
    			<coords x="-1.3" y="2.94" z="1.0"/>
    			<pointSize val="3"/>
    		</element>
    		<element    type="point" label="B">
    			<labelMode val="0"/>
    			<animation step="0.1" speed="1" type="0" playing="false"/>
    			<coords x="2.02" y="3.24" z="1.0"/>
    			<pointSize val="3"/>
    		</element>
    		<!-- Encore un commentaire qui ne va pas --->
    		<musikart player="the boss" style="nursery rhyme"/>
    		<!-- Commentaire -- errone -->
    		<galaxy  code="M31" nickname="Andromede" type="spiraled">
    			<visibility with="eyes"/>
    			<size said="giant" physical="20×44 kpc" angular="92'×197'"/>
    			<mass total="(2-4)×10E11 Msun"    kernel="7×10E7 Msun"/>
    		</galaxy>
    	</construction>
    </geogebra>

    on obtient le résultat 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
    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
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    >>> 
    noms des balises : 'kernel', 'gui', 'element', 'construction', 'geogebra', 'galaxy'
    nbalise = {'kernel': 1, 'element': 1}
     
     
     
     
     
    ================================================================
     
     
    ana['TE><TE'] = {
     
    attributs       : {'--aucun--': 'TE><TE est un code source XML.'} ,
     
    elements_vides  : {} ,
     
    elements_pleins : listElements['TE><TE'] = ['geogebra']    }
     
    ----------------------------------------------------------------
    ana['geogebra'] = {
     
    attributs       : {'format': '3.2'} ,
     
    elements_vides  : {} ,
     
    elements_pleins : listElements['geogebra'] = ['kernel_1', 'gui', 'kernel_2', 'construction']    }
     
     
    BAD LINES de geogebra :
        '\t<jhkgkwjhgdf879769444>'
        ==> Cette ligne semble ne pas etre du tout conforme
     
    ----------------------------------------------------------------
    ana['kernel_1'] = {
     
    attributs       : {'bidon': 'nimportkoi'} ,
     
    elements_vides  : {'region': {'gobi': 'desert', 'serenity': 'lune'} ,
                       'cuvette': {'type': 'plastique'} ,
                       'seau': {'pour': 'la plage'}} ,
     
    elements_pleins : listElements['kernel_1'] = []    }
     
    ----------------------------------------------------------------
    ana['gui'] = {
     
    attributs       : {} ,
     
    elements_vides  : {'font': {'size': '12'} ,
                       'show': {'algebraView': 'true', 'spreadsheetView': 'false'}} ,
     
    elements_pleins : listElements['gui'] = []    }
     
     
    BAD LINES de gui :
        '\t\t<font size="12">'
        ==> Il manque '/>' en bout de ligne.
     
    ----------------------------------------------------------------
    ana['kernel_2'] = {
     
    attributs       : {} ,
     
    elements_vides  : {'continuous': {'   val': 'false'} ,
                       'decimals': {'val': '2'}} ,
     
    elements_pleins : listElements['kernel_2'] = []    }
     
     
    BAD LINES de kernel_2 :
        '\t\t<continuous    val="false"/>'
        ==> Un seul blanc doit suivre le nom.
        '    val="false"'
        ==> Cette chaine n'est pas une chaine d'attributs conforme.
     
    ----------------------------------------------------------------
    ana['construction'] = {
     
    attributs       : {} ,
     
    elements_vides  : {'musikart': {'player': 'the boss', 'style': 'nursery rhyme'} ,
                       'tagada': {'color': 'red', 'effect': 'riples', 'shade': 'metallic'}} ,
     
    elements_pleins : listElements['construction'] = ['element_1', 'element_2', 'galaxy']    }
     
    ----------------------------------------------------------------
    ana['element_1'] = {
     
    attributs       : {'type': 'point', 'label': 'A'} ,
     
    elements_vides  : {'pointSize': {'val': '3'} ,
                       'coords': {'y': '2.94', 'x': '-1.3', 'z': '1.0'} ,
                       'layer': {'val': '0'} ,
                       '-!-': {} ,
                       'labelMode': {'val': '0'}} ,
     
    elements_pleins : listElements['element_1'] = []    }
     
     
    BAD LINES de element_1 :
        ' Commentaire foireux --'
        ==> Cette chaine n'est pas une chaine d'attributs conforme.
        '\t\t\t<-!- Commentaire foireux -->'
        ==> Il manque '/>' en bout de ligne.
     
    ----------------------------------------------------------------
    ana['element_2'] = {
     
    attributs       : {'type': 'point', 'label': 'B'} ,
     
    elements_vides  : {'pointSize': {'val': '3'} ,
                       'animation': {'type': '0', 'step': '0.1', 'speed': '1', 'playing': 'false'} ,
                       'coords': {'y': '3.24', 'x': '2.02', 'z': '1.0'} ,
                       'labelMode': {'val': '0'}} ,
     
    elements_pleins : listElements['element_2'] = []    }
     
     
    BAD LINES de element_2 :
        '    type="point" label="B"'
        ==> Cette chaine n'est pas une chaine d’attributs conforme.
     
    ----------------------------------------------------------------
    ana['galaxy'] = {
     
    attributs       : {'type': 'spiraled', 'code': 'M31', 'nickname': 'Andromede'} ,
     
    elements_vides  : {'mass': {'total': '(2-4)\xd710E11 Msun', '   kernel': '7\xd710E7 Msun'} ,
                       'visibility': {'with': 'eyes'} ,
                       'size': {'said': 'giant', 'angular': "92'\xd7197'", 'physical': '20\xd744 kpc'}} ,
     
    elements_pleins : listElements['galaxy'] = []    }
     
     
    BAD LINES de galaxy :
        '  code="M31" nickname="Andromede" type="spiraled"'
        ==> Cette chaine n'est pas une chaine d’attributs conforme.
        ' total="(2-4)\xd710E11 Msun"    kernel="7\xd710E7 Msun"'
        ==> Cette chaine n'est pas une chaine d'attributs conforme.
     
    ----------------------------------------------------------------
    >>>
    .

  19. #19
    Membre chevronné

    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
    Points : 1 752
    Points
    1 752
    Par défaut
    Merci je testerais cela et te dirais si ta solution me convient.

    C.

  20. #20
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    Je ne comprends pas: tu testerais à quelle condition ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

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