Printing XML beautifully in Python

Keywords: xml Python

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.

Posted by Afser on Sat, 08 Feb 2020 07:55:22 -0800