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 :

Comment modifier le contenu d'un noeud de type texte avec python?


Sujet :

Python

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 14
    Points : 11
    Points
    11
    Par défaut Comment modifier le contenu d'un noeud de type texte avec python?
    Bonjour,

    Voilà mon problème j'ai un fichier xml où j'enregistre la configuration de mon application du type:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    <?xml version="1.0"?>
    <root>
    	<config>
    		<mode>auto</mode>
                    <langue>francais<langue>
    	</config>
    </root>
    La configuration peut changer au cours du temps puisque l'utilisateur à plein pouvoir dessus.
    J'aimerais modifier le texte du noeud mode. Comment puis-je faire ?
    Pour infos, je lis le contenu du fichier xml avec minidom mais je n'ai pas trouvé pour modifier le contenu d'un noeud.

    Merci d'avance à vous.

  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
    Salut,

    Et avec MicroTom?

    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
     
    ch = '''<?xml version="1.0"?>
    <root>
            <config>
                    <mode>auto</mode>
                    <langue>francais<langue>
            </config>
    </root>
     '''
    print ch
     
    RE = '\s+<config>\r?\n\s+<mode>([^<]+)</mode>\r?\n(\s+.+\r?\n)*\s+</config>'
    x,y = re.search(RE,ch).span(1)
     
    chtr = ch[0:x] + raw_input('Entrer la modif : ') + ch[y:]
    print '\n'+chtr

  3. #3
    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 Tinkite82 Voir le message
    J'aimerais modifier le texte du noeud mode. Comment puis-je faire ?
    Je ne sais pas s'il existe une méthode en apparence directe. Pour ma part, j'aurais tendance à lire le contenu du fichier XML, à en faire une copie avec les modifications souhaitées, et enfin à effacer l'ancien fichier.

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 14
    Points : 11
    Points
    11
    Par défaut
    Merci de vos réponses.
    Les possibilités que vous donnez sont faisables mais je voudrais une méthode directe je cherche en faite la bonne api pour faire ça.
    Tu parlais de MicroTom je ne vois pas ce que c'est ?(pour info en tapant "MicroTom python" tu es le premier sur google avec ta réponse lol)

    Personne ne connaît donc cette fameuse api ?

  5. #5
    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
    MicroTom: c’est une blague pour helléniste derrière laquelle il y a:

    - l’opposition mini / micro
    Mini, même si petit, étant plus gros que micro.
    Les regex ne sont pas plus difficiles à mettre en œuvre, à mon avis, que minidom ou autre logiciel ’fait pour’ mais qui se révèlent tout aussi complexes et longs à maîtriser que les regex.

    - remplacer un morceau de chaîne comme je l’ai fait dans mon code, c’est découper une tranche:
    googlise donc “microtome“....


    EDIT:
    helléniste et non pas héléniste

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 14
    Points : 11
    Points
    11
    Par défaut
    Ok j'avais pas compris, je suis pas un spécialiste de la civilisation grec.
    Oui bon je crois que je vais faire un truc "beta" qui efface tout et réécrit tout la configuration dans le fichier xml lors d'un changement si il y a pas d'autre solution.

    Merci à vous

  7. #7
    Membre expérimenté Avatar de pacificator
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 074
    Points : 1 728
    Points
    1 728
    Par défaut
    Bonjour,

    un exemple avec ElementTree,

    prenons le fichier exemple.xml suivant:
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0"?>
    <root>
        <config>
            <mode>auto</mode>
            <langue>francais</langue>
         </config>
    </root>
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    from xml.etree import ElementTree as ET
     
    tree = ET.parse('exemple.xml')
     
    root = tree.getroot()
    mode = root.find('config/mode')
    mode.text = 'manuel'
     
    tree.write('exemple.xml')
     
    print open('exemple.xml').read()
    On obtient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <root>
        <config>
            <mode>manuel</mode>
            <langue>francais</langue>
        </config>
    </root>
    Bon python

  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
    Présenté clé en main par pacificator, ElementTree me paraît moins rébarbatif. On peut d’ailleurs condenser le code ainsi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    from xml.etree import ElementTree as ET
     
    mod = raw_input('Entrer la modification : ')
     
    tree = ET.parse('example.xml')
    tree.getroot().find('config/mode').text = mod
    tree.write('exemple.xml')
     
     
     
    print open('exemple.xml').read()

    Ceci me convainc de l’utilité d’ElementTree. Dont je ne doutais pas d’ailleurs. Il faut juste apprendre à le piloter, et c’est juste de dont j’ai la flemme.
    Pour un cas simple, les regex permettent de se débrouiller facilement et en peu de lignes aussi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import re
     
    mod = raw_input('Entrer la modification : ')
     
    with open('example.xml','r+b') as f:
        chtr = re.sub('(?<=<mode>)[^<]+(?=</mode>)',mod,f.read())
        f.seek(0)
        f.write( chtr )
     
     
    print open('example.xml').read()

  9. #9
    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
    Petit problème avec mon dernier code: si la chaîne remplaçante est plus courte que la chaîne remplacée, le mode r+ fait que l’écriture ne va pas jusqu’au bout du fichier. Il reste donc des caractères intacts du fichier initial en fin de fichier actualisé. Donc faire:



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import re
     
    mod = raw_input('Entrer la modification : ')
     
    with open('example.xml','rb') as f:
        chtr = re.sub('(?<=<mode>)[^<]+(?=</mode>)',mod,f.read())
    with open('example.xml','wb') as f:
        f.write( chtr )
     
     
    print open('example.xml').read()

  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
    Citation Envoyé par pacificator Voir le message
    Bonjour,

    un exemple avec ElementTree,
    ...
    On obtient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <root>
        <config>
            <mode>manuel</mode>
            <langue>francais</langue>
        </config>
    </root>
    Bon python
    Je commence à apprécier ElementTree mais il y a un gros souci avec l'exemple ci-dessus car on perd la ligne ci-dessous qui est hyper importante :
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    <?xml version="1.0"?>
    Peut-on résoudre ce problème directement avec ElementTree ?

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 313
    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 313
    Points : 36 819
    Points
    36 819
    Par défaut
    Salut,

    Personnellement, je préfère utiliser lxml qui est une API au dessus des bibliothèques C libxml2 et libxslt.

    L'API est assez proche de celle d'ElementTree mais concernant votre question: comment mettre les "entêtes" je ne sais pas le faire avec ElementTree!

    Par contre avec lxml, c'est assez simple avec l'ajout de:
    - xml_declaration=True
    - voire: pretty_print=True
    - et éventuellement encoding=...

    - W

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from lxml import etree as ET
    XML = '''<?xml version='1.0' ?>
    <root>
        <config>
            <mode>auto</mode>
            <langue>francais</langue>
         </config>
    </root>'''
    root =ET.XML(XML)
    mode = root.find('config/mode')
    mode.text = 'manuel'
    print ET.tostring(root, xml_declaration=True, pretty_print=True)
    Output:
    Code console : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    (py26_pylons)bash-3.2$ python test_etree.py
    <?xml version='1.0' encoding='ASCII'?>
    <root>
        <config>
            <mode>manuel</mode>
            <langue>francais</langue>
         </config>
    </root>

  12. #12
    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
    J'ai pris 2min pour regarder la doc. officielle de ElementTree.

    Il suffit en fait de remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tree.write(pathOfTheFile)
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tree.write(pathOfTheFile, encoding = "UTF-8")
    Merci quand même à wiztricks (au passage, tu as le droit de me tutoyer).

  13. #13
    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
    il y a un gros souci avec l'exemple ci-dessus car on perd la ligne ci-dessous qui est hyper importante :
    <?xml version="1.0"?>
    Décevant pour ce qui est d’ ElementTree

    Il suffit en fait de remplacer
    tree.write(pathOfTheFile)
    par
    tree.write(pathOfTheFile, encoding = "UTF-8")
    Mais ça ne résoud pas le problème de réécrire un prologue identique à celui qui se trouvait dans le fichier de départ: quand il est inconnu, il faut bien le récupérer d’une manière ou d’une autre dans le fichier et ElementTree ne permet apparemment pas de le faire.




    Ma solution avec regex uniquement reste donc en lice pour un traitement ultra-simple. On peut aussi envisager une écriture-écrasement dans le même fichier ouvert en ’rb+’.
    Mais seulement si c’est vraiment simple, car:

    The first choice you face when parsing a document is whether to adopt an existing parsing library or to roll out your own. And this is a very easy choice: pick an existing library.

    Granted, XML is not a very complex syntax so you can be forgiven for thinking that you can hack your way with regular expressions or other ad-hoc means. In practice it seldom works: XML syntax requires support for multiple encodings and many subtleties, such as CDATA sections or entities. Home-made implementations almost never cater to all these aspects and they create incompatibilities.

    (...)

    Most importantly, never attempt to decode XML documents with ad-hoc code. The risk that you'll create incompatibilities if you fail to implement the standard completely is just too high.

    http://www.ibm.com/developerworks/xm.../x-wxxm38.html
    Mais voici quelque chose de plus nuancé qui me conforte::

    If all you need to do with an XML file is grab some text from within a single node, it might be possible to use a simple regular expression that will probably operate faster than any XML parser.

    In practice, though, this is nearly impossible to get right when the data is at all complex, and I do not recommend it. XML libraries are unvaluable when true data manipulation is required.

    http://www.ibm.com/developerworks/op...x.html?ca=drs-






    En étudiant la librairie lxml porté à notre connaissance par wiztricks, je m’aperçois qu’elle est tout à fait bien:

    http://blog.ianbicking.org/2008/12/1...aping-library/

    People think BeautifulSoup is better at parsing broken HTML. This is not correct. lxml parses broken HTML quite nicely. I haven’t done any thorough testing, but at least the BeautifulSoup broken HTML example http://www.crummy.com/software/Beaut...mentation.html is parsed better by lxml (which knows that <td> elements should go inside <table> elements).

    http://codespeak.net/lxml/lxmldoc-2.2.6.pdf

    » lxml takes all the pain out of XML «
    Stephan Richter

    lxml is a Pythonic binding for the libxml2 and libxslt libraries. It is unique in that it combines the speed and feature completeness of these labraries with the simplicity of a native API, mostly compatible but superior to the well-known ElementTree API.

    http://www.ibm.com/developerworks/op...x.html?ca=drs-
    ou en PDF
    http://download.boulder.ibm.com/ibmd...fparse-pdf.pdf

    Many software products come with the pick-two caveat, meaning that you must choose only two: speed, flexibility, or readability. When used carefully, lxml can provide all three. XML developpers who have struggled with DOM performance or with the event-driven model of SAX now have the chance to work with higher-level pythonic libraries.


    conseil de wiztricks: + 3

  14. #14
    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
    Décevant pour ce qui est d’ ElementTree
    Oui. Il faudrait essayer de voir avec son auteur.

    Citation Envoyé par eyquem
    Mais ça ne résoud pas le problème de réécrire un prologue identique à celui qui se trouvait dans le fichier de départ...
    Pour mon utilisation perso., je travaille en UTF-8 (un changement d'OS m'a fait comprendre la nécessité de choisir ce type d'encodage). De plus, il y a peut-être un moyen de récupérer l'encodage avec ElementTree; je vais regarder cela. Ceci étant dit, cela devrait être automatique.

    Citation Envoyé par eyquem
    Ma solution avec regex uniquement reste donc en lice pour un traitement ultra-simple.
    A titre perso., comme tu le sais, je suis très fâché avec les regex. Je me sens plus à l'aise avec la manière de fonctionner d'outils comme ElementTree, lxml ou pyquerry pour le HTML. Le souci avec lxml est son installation sous Mac, c'est pour cela que je me limite à utiliser ElementTree.

  15. #15
    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
    La doc de ElementTree n’est pas terrible, ceci le confirme:

    http://archives.free.net.ph/message/...9b2908.fr.html

    http://bugs.python.org/issue6488
    (c’est la même file de discussion dans une autre présentation)









    ElementTree n’est pas la seule lib blâmable:

    But it wasn’t immediately obvious from the docutils documentation what series of incantations would achieve my desired results.

    http://halfcooked.com/blog/2010/06/0...redtext-files/

    Ce cas m’a rappelé l’incapacité à trouver comment indiquer à ElemenTree qu’il lui faut récupérer une ligne
    <?xml version="1.0"?>


    L’auteur décrivant comment il y est finalement parvenu, cela donne à espérer qu’il puisse être trouvé de même pour le problème concernant ElementTree.

    C’est dommage qu’une lib soit incluse en built-in dans Python et qu’elle présente une insuffisance, alors que lxml qui est meilleure est une lib tierce.

Discussions similaires

  1. [SimpleXML] Modifier le contenu d'un noeud
    Par michael_MS dans le forum Bibliothèques et frameworks
    Réponses: 17
    Dernier message: 16/10/2008, 15h24
  2. [SimpleXML] Modifier le contenu d'un noeud
    Par Scalp4 dans le forum Bibliothèques et frameworks
    Réponses: 9
    Dernier message: 02/10/2008, 14h59
  3. [XSLT] comment recopier le contenu d'un noeud sans ses fils
    Par st0ne dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 13/09/2007, 11h05
  4. Comment Modifier le contenu de @INC ?
    Par lfa44 dans le forum Langage
    Réponses: 2
    Dernier message: 11/09/2007, 20h55

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