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