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>
Josh Correia
  • 3,807
  • 3
  • 33
  • 50
TheBeardedBerry
  • 1,636
  • 5
  • 20
  • 30
  • 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!? – bluenote10 Dec 24 '13 at 15:36
  • 2
    you can use a function like the one i found here: http://effbot.org/zone/element-lib.htm#prettyprint – Simon Meyer Dec 28 '16 at 17:41
  • @bluenote10 When someone report, the other people will re-report, just to follow something. I'm from Colombia, so sorry for my bad english. – Máxima Alekz Dec 16 '17 at 16:32
  • Related: [Python Bug Tracker - Issue report for Pretty Printing](https://bugs.python.org/issue14465); and [GitHub - proposed pull request](https://github.com/python/cpython/pull/4016). – Stevoisiak Apr 27 '18 at 20:23
  • You can check my answer here: https://stackoverflow.com/a/63373633/268627. As of Python 3.9 there will be a new indent function built-in. – o15a3d4l11s2 Aug 12 '20 at 09:29

2 Answers2

72

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

Stevoisiak
  • 23,794
  • 27
  • 122
  • 225
Maxime Chéramy
  • 17,761
  • 8
  • 54
  • 75
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>
mmmmmm
  • 32,227
  • 27
  • 88
  • 117