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 :

recupérer un arbre de répertoire dans un fichier xml avec LXML


Sujet :

Python

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut recupérer un arbre de répertoire dans un fichier xml avec LXML
    Bonsoir,
    j'ai une arboresence de répertoires, ls -R donne
    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
    .:
    biblio
    dir tree
    DirTree.txt
    lxml_dir to xml.py
    xmldirtree.py
     
    ./biblio:
    Cuisine
    Essais
    Roman
    Science
     
    ./biblio/Cuisine:
    Amerique
    Asie
    France
     
    ./biblio/Cuisine/Amerique:
    le chili sans pleur
     
    ./biblio/Cuisine/Asie:
    le riz de r à z
     
    ./biblio/Cuisine/France:
    escargot pour les nuls.txt
    tête de veau pour tous
     
    ./biblio/Essais:
    Politique
    Religion
     
    ./biblio/Essais/Politique:
    on nous cache tout ondr
     
    ./biblio/Essais/Religion:
    mon curé chez les nudistes
     
    ./biblio/Roman:
    r19s
    r20s
     
    ./biblio/Roman/r19s:
    le vert et le rouge
     
    ./biblio/Roman/r20s:
    ma vie mon oeuvre
     
    ./biblio/Science:
    maths
    physique
     
    ./biblio/Science/maths:
    la table de 1
     
    ./biblio/Science/physique:
    th des ficelles
    Dans un premier temps je voudrais recopier l'arborescence dans un fichier xml.

    Mon code échoue:
    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
    # -*- coding: utf-8 -*-
    """
    Created on Tue Jan 31 13:30:22 2012
     
    @author: Jean-Patrick Pommier
    """
    import lxml.etree as et
    import os
    """
    Lire l'arboresence d'un répertoire projet
                        P
                      / | \
                     A  B  C
                   / |\ |\  |\
                  a  b ca b c e
    Stocker dans un fichier xml
    <P>
        <A>
            <a>
            <b>
            <c>
        </A>
        <B>
            <a>
            <b>
        </B>
        <C>
            <c>
            <e>
        </C>
    </P>
    """
    def makeNodes(parentxml,leveldirlist):
            #print 'parent',parentxml
            print 'chidren',leveldirlist
            for d in leveldirlist:
                child=et.Element(d)
                parentxml.append(child)
     
    if __name__ == '__main__':
        topdir='/home/claire/Applications/ProjetPython/testxml/biblio'
        projetxml=et.Element('Project')#racine       
        parent=projetxml
     
        for roots, dirs, files in os.walk(topdir):
            print roots#, '*',dirs, '*',files,'\n'
            makeNodes(parent,dirs)
     
        print(et.tostring(projetxml,pretty_print=True))
    Tous les sous répertoires sont au même niveau.
    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
    <Project>
      <Roman/>
      <Cuisine/>
      <Essais/>
      <Science/>
      <r20s/>
      <r19s/>
      <Amerique/>
      <France/>
      <Asie/>
      <Religion/>
      <Politique/>
      <maths/>
      <physique/>
    </Project>
    J'ai besoin d'un coup de main pour tranformer les répertoires enfants en répertoires parents.
    Merci.
    Jean-Patrick

  2. #2
    Membre éprouvé

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Points : 1 273
    Points
    1 273
    Par défaut
    Pour autant que je puisse voir, le problème ne vient pas d’XML, mais de ton “main” – os.walk ne recrée pas l’arborescence, c’est à toi de le faire… En stockant dans un dict les nœuds “dossier” avec comme clé leur chemin, par exemple*:

    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
    # -*- coding: utf-8 -*-
    """
    Created on Tue Jan 31 13:30:22 2012
     
    @author: Jean-Patrick Pommier
    """
     
    import lxml.etree as et
    import os
     
    """
    Lire l'arboresence d'un répertoire projet
                        P
                      / | \
                     A  B  C
                   / |\ |\  |\
                  a  b ca b c e
    Stocker dans un fichier xml
    <P>
        <A>
            <a>
            <b>
            <c>
        </A>
        <B>
            <a>
            <b>
        </B>
        <C>
            <c>
            <e>
        </C>
    </P>
    """
     
     
    def makeNodes(node_dirs, root, leveldirlist):
            #print 'parent', parentxml
            print 'chidren', leveldirlist
            for d in leveldirlist:
                child = et.Element(d)
                nodes_dirs[os.path.join(root, d)] = child
                nodes_dirs[root].append(child)
     
     
    if __name__ == '__main__':
        topdir = '/home/claire/Applications/ProjetPython/testxml/biblio'
        projetxml = et.Element('Project')  # racine
        parent = projetxml
        nodes_dirs = {topdir: parent}
     
        for root, dirs, files in os.walk(topdir):
            print root  #, '*',dirs, '*',files,'\n'
            makeNodes(nodes_dirs, root, dirs)
     
        print(et.tostring(projetxml, pretty_print=True))
    Note*: code non testé*!

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Merci,
    J'ai testé, cela fonctionne.
    Dans la réalité, j'ai des répertoires dont le nom est un nombre et xml n'aime pas les nombre comme tag. Je vais essayer de modifier le code de manière à ce que les noeuds de l'arbre aient le même tag avec un attribut, "nom", variable.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 308
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 308
    Points : 36 809
    Points
    36 809
    Par défaut
    Salut,

    Les tags ne sont pas des "données" mais des informations qui décrivent des données associées... Ne serait-il pas plus sage de définir un élément XML associé au répertoire, genre: <repertoire name="string"/>.
    Cela n'interdit pas d'avoir des "fils":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <repertoire name="d1">
        <repertoire name="d2"/>
        <file name="d2"/>
    </repertoire>
    C'est vous qui voyez.

    - W

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Cela me parait sage. Reste à modifier le code en conséquence.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Bonjour,
    J'essaie de modifier le code. Pour l'instant:
    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
    # -*- coding: utf-8 -*-
    """
    Created on Tue Jan 31 13:30:22 2012
     
    @author: 
    """
    import lxml.etree as et
    import os
     
     
    def makeNodes(node_dirs, root, leveldirlist):
            #print 'parent', parentxml
     
            print 'children', leveldirlist
            #print 'node_dirs',node_dirs
            for d in leveldirlist:
                child = et.Element('node',name=d)
                nodes_dirs[os.path.join(root, d)] = child
                nodes_dirs[root].append(child)         
     
    level={}            
    if __name__ == '__main__':
    #    topdir='/home/claire/Applications/ProjetPython/testxml/biblio'
    #    projetxml=et.Element('Project')#racine       
    #    parent=projetxml
    #    
    #    for roots, dirs, files in os.walk(topdir):
    #        print roots#, '*',dirs, '*',files,'\n'
    #        makeNodes(parent,dirs)
        topdir = '/home/claire/Applications/ProjetPython/testxml/biblio'
        #topdir='/home/claire/Applications/ImagesTest/jp'
        projetxml = et.Element('Project')  # racine
        parent = projetxml
        nodes_dirs = {topdir: parent}
     
     
        for root, dirs, files in os.walk(topdir):
            #print root  #, '*',dirs, '*',files,'\n'
            makeNodes(nodes_dirs, root, dirs)
     
        print(et.tostring(projetxml,pretty_print=True))
    ça donne:
    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
    <Project>
      <node name="Roman">
        <node name="r20s"/>
        <node name="r19s"/>
      </node>
      <node name="Cuisine">
        <node name="Amerique"/>
        <node name="France"/>
        <node name="Asie"/>
      </node>
      <node name="Essais">
        <node name="Religion"/>
        <node name="Politique"/>
      </node>
      <node name="Science">
        <node name="maths"/>
        <node name="physique"/>
      </node>
    </Project>
    Comment modifier le code pour que le tag dépende de la profondeur de l'arbre?
    Pour avoir par ex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    <d0 name='Projet'>
       <d1 name='Roman'>
         <d2 name='19e'>
         </d2>
       </d1>
       <d1 name='Science'>
         <d2 name='maths'>
         </d2>
       </d1>
    </d0>

  7. #7
    Membre éprouvé

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Points : 1 273
    Points
    1 273
    Par défaut
    Le plus simple me semble être de passer le niveau à makeNodes –*et pour calculer celui-ci, faire une “comparaison” entre le root courant et celui de départ…

    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
    # -*- coding: utf-8 -*-
    """
    Created on Tue Jan 31 13:30:22 2012
     
    @author: 
    """
    import lxml.etree as et
    import os
     
     
    def makeNodes(node_dirs, root, leveldirlist, root_level):
            #print 'parent', parentxml
            print 'children', leveldirlist
            #print 'node_dirs',node_dirs
     
            for d in leveldirlist:
                child = et.Element("node{}".format(root_level), name=d)
                nodes_dirs[os.path.join(root, d)] = child
                nodes_dirs[root].append(child)
     
    if __name__ == '__main__':
    #    topdir = '/home/claire/Applications/ProjetPython/testxml/biblio'
    #    projetxml = et.Element('Project')  #racine
    #    parent = projetxml
    #
    #    for roots, dirs, files in os.walk(topdir):
    #        print roots  #, '*',dirs, '*',files,'\n'
    #        makeNodes(parent, dirs)
        topdir = '/home/claire/Applications/ProjetPython/testxml/biblio'
        #topdir = '/home/claire/Applications/ImagesTest/jp'
        projetxml = et.Element('Project')  # racine
        parent = projetxml
        nodes_dirs = {topdir: parent}
     
        ln_root = len(topdir)
        for root, dirs, files in os.walk(topdir):
            #print root  #, '*',dirs, '*',files,'\n'
            lvl = root[ln_root:].count(os.path.sep)
            makeNodes(nodes_dirs, root, dirs, lvl)
     
        print(et.tostring(projetxml,pretty_print=True))
    L’intérêt étant dans cette ligne*: lvl = root[ln_root:].count(os.path.sep), qui retire (d’après sa longueur) la partie “topdir” du root courant, avant de compter les occurrences du séparateur de chemin (os.path.sep).

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Bonjour,

    Chez moi, le code génère un message:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Traceback (most recent call last):
      File "/media/Elements__/Science/Projets/databasexml.py", line 32, in <module>
        makeNodes(nodes_dirs, root, dirs, lvl) 
      File "/media/Elements__/Science/Projets/databasexml.py", line 18, in makeNodes
        child = et.Element("node{}".format(root_level), name=d)
    ValueError: zero length field name in format
    Ce message disparait en supprimant les accolades:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    child = et.Element("node".format(root_level), name=d)
    mais si on fait cela, les nodes ne sont pas numérotés selon la profondeur:
    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
    <Project>
      <node name="A">
        <node name="a"/>
        <node name="b"/>
      </node>
      <node name="B">
        <node name="a"/>
        <node name="b"/>
      </node>
      <node name="C">
        <node name="a"/>
        <node name="b"/>
        <node name="c"/>
        <node name="d"/>
      </node>
    </Project>
    Merci pour l'instruction permettant de reccupérer la profondeur de l'arbre.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 91
    Points : 65
    Points
    65
    Par défaut
    Rebonjour,
    En cherchant des info sur la méthode format(), cela donne:
    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
    # -*- coding: utf-8 -*-
     
    """
    Created on Tue Jan 31 13:30:22 2012
     
    @author: 
    """
    import lxml.etree as et
    import os
     
     
    def makeNodes(node_dirs, root, leveldirlist, root_level):
        print '*********makeNodes******'
        print 'children', leveldirlist
        print 'node_dirs',node_dirs
        print 'root level',root_level
        for d in leveldirlist:
            child = et.Element("node{0}".format(root_level), name=d)
            nodes_dirs[os.path.join(root, d)] = child
            nodes_dirs[root].append(child)
     
    if __name__ == '__main__':
        topdir = '/media/Elements__/Science/Projets/projet'
        projetxml = et.Element('Project')  # racine
        parent = projetxml
        nodes_dirs = {topdir: parent}
        ln_root = len(topdir)
        print 'ln_root',ln_root
        for root, dirs, files in os.walk(topdir):
            #print root  #, '*',dirs, '*',files,'\n'
            lvl = root[ln_root:].count(os.path.sep)
            makeNodes(nodes_dirs, root, dirs, lvl) 
        print(et.tostring(projetxml,pretty_print=True))
    et ça roule
    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
    <Project>
      <node0 name="A">
        <node1 name="a"/>
        <node1 name="b"/>
      </node0>
      <node0 name="B">
        <node1 name="a"/>
        <node1 name="b"/>
      </node0>
      <node0 name="C">
        <node1 name="a"/>
        <node1 name="b"/>
        <node1 name="c"/>
        <node1 name="d"/>
      </node0>
    </Project>
    merci encore.

  10. #10
    Membre éprouvé

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Points : 1 273
    Points
    1 273
    Par défaut
    Désolé pour .format(), le truc a dû changer un peu par rapport à py2 (je ne fais que du py3, donc… )..

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

Discussions similaires

  1. [JDOM] Ecrire dans un fichier XML avec JDOM
    Par pomolo11 dans le forum Format d'échange (XML, JSON...)
    Réponses: 2
    Dernier message: 26/12/2013, 00h19
  2. [JDOM] Suppression d'un élément dans un fichier XML avec JDOM
    Par pomolo11 dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 08/12/2013, 11h36
  3. [JDOM] Comment insérer une image .jpg dans un fichier xml avec JDOM ?
    Par Ardillon dans le forum Format d'échange (XML, JSON...)
    Réponses: 2
    Dernier message: 05/07/2013, 15h08
  4. [JDOM] Insérer les données saisies dans un formulaire dans un fichier XML avec JDOM
    Par fruwen7 dans le forum Format d'échange (XML, JSON...)
    Réponses: 21
    Dernier message: 03/09/2012, 14h45
  5. ecrire dans un fichier xml avec php
    Par gilbertbicot dans le forum Langage
    Réponses: 1
    Dernier message: 21/01/2009, 13h10

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