Je génère un document XML en Python à l'aide de ElementTree
, mais la fonction tostring
n'inclut pas de déclaration XML lors de la conversion en texte brut.
from xml.etree.ElementTree import Element, tostring
document = Element('outer')
node = SubElement(document, 'inner')
node.NewValue = 1
print tostring(document) # Outputs "<outer><inner /></outer>"
J'ai besoin que ma chaîne inclue la déclaration XML suivante:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
Cependant, il ne semble pas y avoir de moyen documenté de le faire.
Existe-t-il une méthode appropriée pour rendre la déclaration XML dans une variable ElementTree
?
Je suis surpris de constater qu'il ne semble pas y avoir de solution avec ElementTree.tostring()
. Vous pouvez cependant utiliser ElementTree.ElementTree.write()
pour écrire votre document XML dans un faux fichier:
from io import BytesIO
from xml.etree import ElementTree as ET
document = ET.Element('outer')
node = ET.SubElement(document, 'inner')
et = ET.ElementTree(document)
f = BytesIO()
et.write(f, encoding='utf-8', xml_declaration=True)
print(f.getvalue()) # your XML file, encoded as UTF-8
Voir cette question . Même à ce moment-là, je ne pense pas que vous puissiez obtenir votre attribut "autonome" sans écrire vous-même au préalable.
Je voudrais utiliser lxml (voir http://lxml.de/api.html ).
Ensuite vous pouvez:
from lxml import etree
document = etree.Element('outer')
node = etree.SubElement(document, 'inner')
print(etree.tostring(document, xml_declaration=True))
Si vous incluez le encoding='utf8'
, vous aurez un en-tête XML :
xml.etree.ElementTree.tostring écrit une déclaration de codage XML avec encoding = 'utf8'
Exemple de code Python 2:
import xml.etree.ElementTree as ElementTree
tree = ElementTree.ElementTree(
ElementTree.fromstring('<xml><test>123</test></xml>')
)
root = tree.getroot()
print 'without:'
print ElementTree.tostring(root, method='xml')
print
print 'with:'
print ElementTree.tostring(root, encoding='utf8', method='xml')
Sortie:
without:
<xml><test>123</test></xml>
with:
<?xml version='1.0' encoding='utf8'?>
<xml><test>123</test></xml>
J'ai rencontré ce problème récemment, après avoir fouillé dans le code, j'ai trouvé l'extrait de code suivant qui définit la fonction ElementTree.write
def write(self, file, encoding="us-ascii"):
assert self._root is not None
if not hasattr(file, "write"):
file = open(file, "wb")
if not encoding:
encoding = "us-ascii"
Elif encoding != "utf-8" and encoding != "us-ascii":
file.write("<?xml version='1.0' encoding='%s'?>\n" %
encoding)
self._write(file, self._root, encoding, {})
La réponse est donc: si vous avez besoin d'écrire l'en-tête XML dans votre fichier, définissez l'argument encoding
autre que utf-8
ou us-ascii
, par exemple. UTF-8
Exemple de travail minimal avec l'utilisation du package ElementTree
:
import xml.etree.ElementTree as ET
document = ET.Element('outer')
node = ET.SubElement(document, 'inner')
node.text = '1'
res = ET.tostring(document, encoding='utf8', method='xml').decode()
print(res)
la sortie est:
<?xml version='1.0' encoding='utf8'?>
<outer><inner>1</inner></outer>
Je voudrais utiliser ET :
try:
from lxml import etree
print("running with lxml.etree")
except ImportError:
try:
# Python 2.5
import xml.etree.cElementTree as etree
print("running with cElementTree on Python 2.5+")
except ImportError:
try:
# Python 2.5
import xml.etree.ElementTree as etree
print("running with ElementTree on Python 2.5+")
except ImportError:
try:
# normal cElementTree install
import cElementTree as etree
print("running with cElementTree")
except ImportError:
try:
# normal ElementTree install
import elementtree.ElementTree as etree
print("running with ElementTree")
except ImportError:
print("Failed to import ElementTree from any known place")
document = etree.Element('outer')
node = etree.SubElement(document, 'inner')
print(etree.tostring(document, encoding='UTF-8', xml_declaration=True))
Une autre option assez simple consiste à concaténer l'en-tête souhaité avec la chaîne de caractères xml comme ceci:
xml = (bytes('<?xml version="1.0" encoding="UTF-8"?>\n', encoding='utf-8') + ET.tostring(root))
xml = xml.decode('utf-8')
with open('invoice.xml', 'w+') as f:
f.write(xml)
Cela fonctionne si vous voulez simplement imprimer. Obtenir une erreur lorsque j'essaie de l'envoyer dans un fichier ...
import xml.dom.minidom as minidom
import xml.etree.ElementTree as ET
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
def prettify(elem):
rough_string = ET.tostring(elem, 'utf-8')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent=" ")
Je n'ai trouvé aucune alternative pour ajouter l'argument standalone
dans la documentation, j'ai donc adapté la fonction ET.tosting
pour le prendre comme argument.
from xml.etree import ElementTree as ET
# Sample
document = ET.Element('outer')
node = ET.SubElement(document, 'inner')
et = ET.ElementTree(document)
# Function that you need
def tostring(element, declaration, encoding=None, method=None,):
class dummy:
pass
data = []
data.append(declaration+"\n")
file = dummy()
file.write = data.append
ET.ElementTree(element).write(file, encoding, method=method)
return "".join(data)
# Working example
xdec = """<?xml version="1.0" encoding="UTF-8" standalone="no" ?>"""
xml = tostring(document, encoding='utf-8', declaration=xdec)