import xml.dom.minidom
dom = xml.dom.minidom.parse(xml_fname) # or xml.dom.minidom.parseString(xml_string)
pretty_xml_as_string = dom.toprettyxml()
Answer from Ben Noland on Stack Overflowimport xml.dom.minidom
dom = xml.dom.minidom.parse(xml_fname) # or xml.dom.minidom.parseString(xml_string)
pretty_xml_as_string = dom.toprettyxml()
lxml is recent, updated, and includes a pretty print function
import lxml.etree as etree
x = etree.parse("filename")
print etree.tostring(x, pretty_print=True)
Check out the lxml tutorial: https://lxml.de/tutorial.html
Videos
Here's how to parse from a text string to the lxml structured data type.
Python 2:
from lxml import etree
xml_str = "<parent><child>text</child><child>other text</child></parent>"
root = etree.fromstring(xml_str)
print etree.tostring(root, pretty_print=True)
Python 3:
from lxml import etree
xml_str = "<parent><child>text</child><child>other text</child></parent>"
root = etree.fromstring(xml_str)
print(etree.tostring(root, pretty_print=True).decode())
Outputs:
<parent>
<child>text</child>
<child>other text</child>
</parent>
I use the lxml library, and there it's as simple as
>>> print(etree.tostring(root, pretty_print=True))
You can do that operation using any etree, which you can either generate programmatically, or read from a file.
If you're using the DOM from PyXML, it's
import xml.dom.ext
xml.dom.ext.PrettyPrint(doc)
That prints to the standard output, unless you specify an alternate stream.
http://pyxml.sourceforge.net/topics/howto/node19.html
To directly use the minidom, you want to use the toprettyxml() function.
http://docs.python.org/library/xml.dom.minidom.html#xml.dom.minidom.Node.toprettyxml
I simply solved it with the indent() function:
xml.etree.ElementTree.indent(tree, space=" ", level=0)Appends whitespace to the subtree to indent the tree visually. This can be used to generate pretty-printed XML output. tree can be anElementorElementTree.spaceis the whitespace string that will be inserted for each indentation level, two space characters by default. For indenting partial subtrees inside of an already indented tree, pass the initial indentation level aslevel.
tree = ET.ElementTree(root)
ET.indent(tree, space="\t", level=0)
tree.write(file_name, encoding="utf-8")
Note, the indent() function was added in Python 3.9.
Whatever your XML string is, you can write it to the file of your choice by opening a file for writing and writing the string to the file.
from xml.dom import minidom
xmlstr = minidom.parseString(ET.tostring(root)).toprettyxml(indent=" ")
with open("New_Database.xml", "w") as f:
f.write(xmlstr)
There is one possible complication, especially in Python 2, which is both less strict and less sophisticated about Unicode characters in strings. If your toprettyxml method hands back a Unicode string (u"something"), then you may want to cast it to a suitable file encoding, such as UTF-8. E.g. replace the one write line with:
f.write(xmlstr.encode('utf-8'))
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
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>