def prettyPrint()

in tools/PrettyXML.py [0:0]


def prettyPrint(elem: ET.Element, newLine: str = '\n', sort: str = None, singleIndent: str = '  ', level: int = 0):
    """
    Sorts and indents the provided ElementTree
    :param elem: the ElementTree to beautify
    :param newLine: the string to create a new line (this is NOT a LF or CRLF, it is a platform-agnostic new line symbol)
    :param sort: the name of the attribute which is used to sort sibling XML elements
    :param singleIndent: the string of whitespaces used to create indentation
    :param level: the current depth of recursive prettyPrint() call
    """
    # Based on the code snipped published at http://effbot.org/zone/element-lib.htm#prettyprint

    i = newLine + level * singleIndent

    # since Python 3.7, dict preserves the order of the inserted elements yet it won't allow to reorder them
    # since ElementTree uses a dict for element attributes' storage
    # so we are going to empty that dict and then repopulate it in desired order:
    # first is the 'sort' attribute then the rest in alphabet order
    if sort and sort in elem.attrib.keys():
        sortValue = elem.attrib.pop(sort)       # first extract the sort order defining attribute
        tmp = {sort: sortValue}                 # and add it as the first element
        for key in sorted(iter(elem.attrib)):   # then copy the remaining attributes in alphabetic order
            tmp[key] = elem.attrib[key]
        elem.attrib.clear()                     # now clear...
        for key in iter(tmp):                   # ... and repopulate the dict of attributes
            elem.attrib[key] = tmp[key]         #     in the desired order

    if len(elem) == 0:
        # if has no child elements
        if level > 0 and empty(elem.tail):
            elem.tail = i

    else:
        # if has child elements
        # sort top level elements by tag name in reverse order
        # sort all other levels' elements by the specified attribute's value
        if level == 0:
            if sort:
                # sort by tag name
                # for XML comment nodes child.tag is a function, not a string
                # chr(0x10FFFF) is the last possible char
                elem[:] = sorted(elem, key=lambda child:
                    child.tag if child.tag and not inspect.isfunction(child.tag)
                    else chr(0x10FFFF), reverse=True)
        else:
            if sort:
                # sort by specified attribute's values
                elem[:] = sorted(elem, key=lambda child: child.get(sort) if child.get(sort) else '')

        if empty(elem.text):
            elem.text = i + singleIndent
        if empty(elem.tail):
            elem.tail = i

        # recursively pretty print each child element
        lastChild = None
        for child in elem:
            prettyPrint(child, newLine, sort, singleIndent, level + 1)
            lastChild = child

        if empty(lastChild.tail):
            lastChild.tail = i