67

I am trying to use xml.etree.ElementTree to write out xml files with Python. The issue is that they keep getting generated in a single line. I want to be able to easily reference them so if it's possible I would really like to be able to have the file written out cleanly.

This is what I am getting:

<Language><En><Port>Port</Port><UserName>UserName</UserName></En><Ch><Port>IP地址</Port><UserName>用户名称</UserName></Ch></Language>

This is what I would like to see:

<Language>
    <En>
        <Port>Port</Port>
        <UserName>UserName</UserName>
    </En>
    <Ch>
        <Port>IP地址</Port>
        <UserName>用户名称</UserName>
    </Ch>
</Language>
5
  • 55
    This is not a true duplicate: The other question leaves the possibility to use any XML library. This question asks specifically for a solution when you are already working with the built-in element tree library. Imho it makes perfect sense to ask this question specifically for this library, because it is apparently a missing feature!? Commented Dec 24, 2013 at 15:36
  • 2
    you can use a function like the one i found here: effbot.org/zone/element-lib.htm#prettyprint Commented Dec 28, 2016 at 17:41
  • 1
    @bluenote10 When someone report, the other people will re-report, just to follow something. I'm from Colombia, so sorry for my bad english. Commented Dec 16, 2017 at 16:32
  • Related: Python Bug Tracker - Issue report for Pretty Printing; and GitHub - proposed pull request. Commented Apr 27, 2018 at 20:23
  • You can check my answer here: stackoverflow.com/a/63373633/268627. As of Python 3.9 there will be a new indent function built-in. Commented Aug 12, 2020 at 9:29

2 Answers 2

74

You can use the function toprettyxml() from xml.dom.minidom in order to do that:

def prettify(elem):
    """Return a pretty-printed XML string for the Element.
    """
    rough_string = ElementTree.tostring(elem, 'utf-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="\t")

The idea is to print your Element in a string, parse it using minidom and convert it again in XML using the toprettyxml function.

Source: http://pymotw.com/2/xml/etree/ElementTree/create.html

Sign up to request clarification or add additional context in comments.

7 Comments

This adds extra lines. Not sure I'd call that pretty.
For a large file though this requires reparsing the whole XML. hmm...
@steve: Not only does that add another line, the data is processed like this: convert the XML tree to string, convert it back to an XML tree, and then convert it back to a string. That's not pretty, that's completely out of the question.
At least it works out of the box with a normal Python installation.
@RaúlSalinas-Monteagudo Not for my Python installation. Unfortunately I have the displeasure of working in an environment where lxml, bs4, xmltodict, stdio, numpy, etc. don't exist and can't be easily installed. Sorry just ranting... Now if only I could find a one-line solution for an out-dated and unsupported Python 2.7...
|
24

You could use the library lxml (Note top level link is now spam) , which is a superset of ElementTree. Its tostring() method includes a parameter pretty_print - for example:

>>> print(etree.tostring(root, pretty_print=True))
<root>
  <child1/>
  <child2/>
  <child3/>
</root>

6 Comments

"pretty_print=True" does not work for me, and I do not why
etree.tostring(root, pretty_print=True).decode() works!
Yes. But lxml does not support default namespace very well.
It supportds namespaces much better than other libraries :) Also that link is now dead and a spam
This answer does not refer to xml.etree.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.