Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

xml.etree.ElementTree: Copier une balise d'un fichier "Source.xml" vers "Destination.xml"

+2 votes

Je souhaite copier une balise d'un fichier xml vers un autre fichier xml sans perdre la structure du fichier destination.

demandé 12-Jan-2016 par anonyme

C'est faisable avec etree non ? Quel problème rencontre-tu ?

4 Réponses

–2 votes

Une solution serait de parcourir et lire ton fichier source ligne par ligne via

line_fichier_source.readline()

Ensuite de créer ton fichier destination, et d'écrire dedans ligne par ligne avec

fichier_destination.write(line_fichier_source)

ps : sources 1 ,2

répondu 12-Jan-2016 par boblinux (3,092 points)

C'est un peu atroce comme solution pour manipuler du XML... Si une balise est sur plusieurs lignes, ou que tu as plusieurs balises pas ligne, tu fais quoi ?

le truc c que la question est tellement vague et imprecise, que forcement les chances de repondre a coter s en suivent.

Si la balise est sur plusieur lignes ca ne changera rien, dans le fichier destination elle sera aussi sur plusieurs lignes :-)

Dans ce cas, tu te retrouve à devoir gérer le parsing XML pour trouver la balise que tu cherches, ce qui n'est pas très fun.

Mais c'est vrai que la question est trop floue.

il faudrait savoir le sous entendu de "perdre la structure du fichier" pour aller plus loin :-\

Un peu plus de précisions!

Le fichier de destination comporte:
Une première balise :
<?xml version="1.0" encoding="ISO-8859-1"?>
Une seconde balise :




Une section commentaire :
<!--Mon commentaire-->

Ce que je souhaite, c'est ajouter une balise "Balise3" à la suite de "Balise2".

Avec etree, j'arrive bien à insérer la Balise3 au bon endroit, mais le problème est que mon dans le fichier "Destination.xml" modifié, je perds la première balise ainsi que la section commentaire, seul l'arbre MaBalise se retrouve dans le fichier.

En espérant avoir été un peu plus clair.

Et si tu nous montrais un peu de code tout simplement ? Tu as juste dû mal t'y prendre, à mon avis.

+1 vote

D'après les précisions données en commentaire :

  • pour ne pas perdre les commentaires d'un fichier XML, il vaut mieux employer lxml, le parser natif de python ne stocke pas les commentaires dans l'arbre. (source)
  • pour ne pas perdre la déclaration d'entête (qui n'est pas à considérer comme une balise) - ce qui je pense t'es arrivé - réfère toi à la doc.
répondu 13-Jan-2016 par yoch (2,312 points)
edité 13-Jan-2016 par yoch
0 votes

Utilise lxml, qui garde les commentaires. Pour garder aussi le header, il tu peux utiliser xml_declaration et encoding:

from lxml import etree
from io import BytesIO

# c'est juste un exemple du type de xml que tu peux gérer
# ce code là n'est pas ce qui résout ton problème
tree = etree.parse(BytesIO('''<?xml version="1.0" encoding="utf8"?>
 <!-- foo -->
  <root>
   <a>bar</a>
 </root>
'''.encode('utf8')))

# si tu mets xml_declaration à True et que tu force l'encoding, tout est gardé
xml = etree.tostring(tree, xml_declaration=True, encoding=tree.docinfo.encoding)
print(xml.decode('utf8'))

Ce qui affiche:

<?xml version='1.0' encoding='utf8'?>
<!-- foo --><root>
   <a>bar</a>
 </root>

Après la structure est conservée, mais pas le formatage exacte.

répondu 3-Fev-2016 par Sam (4,978 points)
0 votes

La question est assez vague mais d'après ce que j'ai compris je ferais ceci:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from lxml import etree

XML= """
<tree>
    <!-- foobar -->
    <first_tag sub_attribute='1'>
        <content>foor</content>
    </first_tag>
    <!-- foobar again-->
    <second_tag sub_attribute='2'>
        <content>bar</content>
    </second_tag>
</tree>"""

parser = etree.XMLParser(remove_blank_text=True)
tag = etree.fromstring(XML, parser)

find_tag = tag.find("second_tag") #trouve le tag après lequel tu veux ajouter ta "Balise3"
tag_to_insert = etree.Element("third_tag", sub_attribute="3") #construit "Balise3"
subtext = etree.SubElement(tag_to_insert, "content") #définit le subtag de "Balise3"
subtext.text = "foobar" #définit le contenu a injecter dans le subtag de "Balise3"
find_tag.addnext(tag_to_insert) # ajoute le tag "Balise3"

print etree.tostring(tag, pretty_print=True)

ce qui produit:

<tree>
  <!-- foobar -->
  <first_tag sub_attribute="1">
    <content>foor</content>
  </first_tag>
  <!-- foobar again-->
  <second_tag sub_attribute="2">
    <content>bar</content>
  </second_tag>
  <third_tag sub_attribute="3">
    <content>foobar</content>
  </third_tag>
</tree>
répondu 3-Fev-2016 par barnumbirr (2,750 points)
...