Skip to content

Instantly share code, notes, and snippets.

@phalt
Created August 28, 2020 01:50
Show Gist options
  • Save phalt/b5cdf3d3d5e91879fd09429adb070244 to your computer and use it in GitHub Desktop.
Save phalt/b5cdf3d3d5e91879fd09429adb070244 to your computer and use it in GitHub Desktop.
Python dictionary to xml string
from xml.etree.ElementTree import Element, tostring
def dict_to_xml(tag: str, d: dict) -> str:
"""
Converts a Python dictionary to an XML tree, and then returns
it as a string.
Works with recursively nested dictionaries!
"tag" is the name of the top-level XML tag.
"""
elem = Element(tag)
def _d_to_x(elem, d):
for key, val in d.items():
child = Element(key)
if isinstance(val, dict):
elem.append(_d_to_x(Element(key), val))
else:
child.text = str(val)
elem.append(child)
return elem
return tostring(_d_to_x(elem, d)).decode("utf-8")
@Xonxt
Copy link

Xonxt commented Mar 4, 2022

Thanks for this!
A small addition, if you like. To also use pretty formatting with an indent, and handle lists.
List elements will be added with the same root name, e,g, something like

{'object': [
 {'b': 1},
 {'b': 2}
]}

will be converted to:

<root>
  <object>
    <b>1</b>
  </object>
  <object>
    <b>2</b>
  </object>
</root>

Here's the modification:

from xml.etree.ElementTree import Element, tostring
from xml.dom import minidom

def dict_to_xml(tag: str, d: dict, indent=2):
    elem = Element(tag)

    def _d_to_x(elem, d):
        for key, val in d.items():

            if not isinstance(val, list):
                child = Element(key)

            if isinstance(val, dict):
                elem.append(_d_to_x(Element(key), val))
            elif isinstance(val, list):
                for l in val:
                    elem.append(_d_to_x(Element(key), l))
            else:
                child.text = str(val)
                elem.append(child)

        return elem

    # prettify
    xml_string = tostring(_d_to_x(elem, d)).decode("utf-8")
    xml_string = minidom.parseString(xml_string)
    xml_string = xml_string.toprettyxml(indent=' ' * indent)  

    return xml_string

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment