What is the best way (or ways) to print XML beautifully in Python?
#1 building
If you have xmllint, you can generate a subprocess and use it. Xmllint -- format < File > its input XML is beautifully printed to standard output.
Note that this method uses a program external to python, which makes it a little hack.
def pretty_print_xml(xml): proc = subprocess.Popen( ['xmllint', '--format', '/dev/stdin'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, ) (output, error_output) = proc.communicate(xml); return output print(pretty_print_xml(data))
#2 building
import xml.dom.minidom dom = xml.dom.minidom.parse(xml_fname) # or xml.dom.minidom.parseString(xml_string) pretty_xml_as_string = dom.toprettyxml()
#3 building
I tried to edit the "ade" answer above, but Stack Overflow did not allow me to edit after initially providing anonymous feedback. This is the wrong version of the function used to exquisitely print ElementTree.
def indent(elem, level=0, more_sibs=False): i = "\n" if level: i += (level-1) * ' ' num_kids = len(elem) if num_kids: if not elem.text or not elem.text.strip(): elem.text = i + " " if level: elem.text += ' ' count = 0 for kid in elem: indent(kid, level+1, count < num_kids - 1) count += 1 if not elem.tail or not elem.tail.strip(): elem.tail = i if more_sibs: elem.tail += ' ' else: if level and (not elem.tail or not elem.tail.strip()): elem.tail = i if more_sibs: elem.tail += ' '
#4 building
I solved the problem in a few lines of code, opening the file, traversing the file, adding indents, and saving again. I'm working on small xml files and don't want to add dependencies or install more libraries for users. In any case, that's what I end up with:
f = open(file_name,'r') xml = f.read() f.close() #Removing old indendations raw_xml = '' for line in xml: raw_xml += line xml = raw_xml new_xml = '' indent = ' ' deepness = 0 for i in range((len(xml))): new_xml += xml[i] if(i<len(xml)-3): simpleSplit = xml[i:(i+2)] == '><' advancSplit = xml[i:(i+3)] == '></' end = xml[i:(i+2)] == '/>' start = xml[i] == '<' if(advancSplit): deepness += -1 new_xml += '\n' + indent*deepness simpleSplit = False deepness += -1 if(simpleSplit): new_xml += '\n' + indent*deepness if(start): deepness += 1 if(end): deepness += -1 f = open(file_name,'w') f.write(new_xml) f.close()
It works for me, maybe someone will use it:)
#5 building
from yattag import indent pretty_string = indent(ugly_string)
It does not add spaces or line breaks within a text node unless you require the following command:
indent(mystring, indent_text = True)
You can specify what indentation units should be and what line breaks should be.
pretty_xml_string = indent( ugly_xml_string, indentation = ' ', newline = '\r\n' )
This document is located in http://www.yattag.org On the homepage.