Skip to main content

How to Convert Lists to XML in Python

XML (Extensible Markup Language) is a widely used format for storing and exchanging structured data between systems. Converting Python lists to XML is a common task when building APIs, generating configuration files, creating data exports, or interfacing with systems that consume XML data.

In this guide, you will learn multiple methods to convert Python lists to XML, from the built-in ElementTree module to the minidom parser and third-party libraries, with practical examples for different data structures.

Python's built-in ElementTree module provides a simple and efficient API for creating, reading, and writing XML documents. It represents the XML document as a tree of elements and is the recommended approach for most use cases.

Basic List to XML Conversion

import xml.etree.ElementTree as ET

fruits = ["Apple", "Banana", "Cherry", "Date", "Elderberry"]

# Create the root element
root = ET.Element("fruits")

# Add each list item as a child element
for fruit in fruits:
item = ET.SubElement(root, "fruit")
item.text = fruit

# Pretty print (Python 3.9+) and display
tree = ET.ElementTree(root)
ET.indent(tree, space=" ")

print(ET.tostring(root, encoding="unicode"))

Output:

<fruits>
<fruit>Apple</fruit>
<fruit>Banana</fruit>
<fruit>Cherry</fruit>
<fruit>Date</fruit>
<fruit>Elderberry</fruit>
</fruits>

To write the XML to a file:

tree.write("fruits.xml", encoding="utf-8", xml_declaration=True)

Converting a List of Dictionaries to XML

A more practical scenario involves converting structured data, such as a list of dictionaries, into XML with nested elements:

import xml.etree.ElementTree as ET

employees = [
{"name": "Alice", "department": "Engineering", "salary": "90000"},
{"name": "Bob", "department": "Marketing", "salary": "75000"},
{"name": "Charlie", "department": "Sales", "salary": "68000"}
]

root = ET.Element("employees")

for emp in employees:
employee = ET.SubElement(root, "employee")
for key, value in emp.items():
child = ET.SubElement(employee, key)
child.text = value

tree = ET.ElementTree(root)
ET.indent(tree, space=" ")

print(ET.tostring(root, encoding="unicode"))

Output:

<employees>
<employee>
<name>Alice</name>
<department>Engineering</department>
<salary>90000</salary>
</employee>
<employee>
<name>Bob</name>
<department>Marketing</department>
<salary>75000</salary>
</employee>
<employee>
<name>Charlie</name>
<department>Sales</department>
<salary>68000</salary>
</employee>
</employees>

Using Attributes Instead of Child Elements

Sometimes data is better represented as XML attributes rather than child elements, especially for simple metadata:

import xml.etree.ElementTree as ET

products = [
{"id": "1", "name": "Laptop", "price": "999"},
{"id": "2", "name": "Phone", "price": "699"},
{"id": "3", "name": "Tablet", "price": "329"}
]

root = ET.Element("catalog")

for product in products:
item = ET.SubElement(root, "product")
for key, value in product.items():
item.set(key, value) # Set as attribute instead of child element

tree = ET.ElementTree(root)
ET.indent(tree, space=" ")
print(ET.tostring(root, encoding="unicode"))

Output:

<catalog>
<product id="1" name="Laptop" price="999" />
<product id="2" name="Phone" price="699" />
<product id="3" name="Tablet" price="329" />
</catalog>
When to Use Attributes vs Child Elements
  • Use attributes for simple metadata like IDs, names, or single values that will not contain special characters or span multiple lines.
  • Use child elements for complex data, multi-line text, or values that might contain characters reserved in XML.

Using xml.dom.minidom

The minidom module provides a DOM (Document Object Model) interface for creating XML. It is more verbose than ElementTree but offers built-in pretty printing without requiring Python 3.9+:

from xml.dom.minidom import Document

colors = ["Red", "Green", "Blue", "Yellow", "Purple"]

# Create the document and root element
doc = Document()
root = doc.createElement("colors")
doc.appendChild(root)

# Add each list item
for color in colors:
element = doc.createElement("color")
text_node = doc.createTextNode(color)
element.appendChild(text_node)
root.appendChild(element)

# Generate pretty-printed XML
xml_string = doc.toprettyxml(indent=" ")
print(xml_string)

Output:

<?xml version="1.0" ?>
<colors>
<color>Red</color>
<color>Green</color>
<color>Blue</color>
<color>Yellow</color>
<color>Purple</color>
</colors>

The toprettyxml() method automatically adds the XML declaration and formats the output with the specified indentation.

Building a Reusable Conversion Function

For production use, a flexible function that handles different list structures keeps your code DRY:

import xml.etree.ElementTree as ET

def list_to_xml(data, root_name="root", item_name="item"):
"""
Convert a list to a formatted XML string.

Args:
data: A list of values, dicts, or nested lists.
root_name: Name of the root XML element.
item_name: Name for each list item element.

Returns:
A formatted XML string with declaration.
"""
root = ET.Element(root_name)

for item in data:
element = ET.SubElement(root, item_name)

if isinstance(item, dict):
for key, value in item.items():
child = ET.SubElement(element, str(key))
child.text = str(value)
elif isinstance(item, (list, tuple)):
for sub_item in item:
sub = ET.SubElement(element, "value")
sub.text = str(sub_item)
else:
element.text = str(item)

tree = ET.ElementTree(root)
ET.indent(tree, space=" ")
return ET.tostring(root, encoding="unicode", xml_declaration=True)

Usage Examples

Example 1: list of values

# Simple list of values
print(list_to_xml(["Apple", "Banana", "Cherry"], "fruits", "fruit"))

Output:

<?xml version='1.0' encoding='utf-8'?>
<fruits>
<fruit>Apple</fruit>
<fruit>Banana</fruit>
<fruit>Cherry</fruit>
</fruits>

Example 2: list of dictionaries

# List of dictionaries
users = [
{"name": "Alice", "role": "Admin"},
{"name": "Bob", "role": "User"}
]
print(list_to_xml(users, "users", "user"))

Output:

<?xml version='1.0' encoding='utf-8'?>
<users>
<user>
<name>Alice</name>
<role>Admin</role>
</user>
<user>
<name>Bob</name>
<role>User</role>
</user>
</users>

Example 3: netsted lists

# Nested lists (e.g., a matrix)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(list_to_xml(matrix, "matrix", "row"))

Output:

<?xml version='1.0' encoding='utf-8'?>
<matrix>
<row>
<value>1</value>
<value>2</value>
<value>3</value>
</row>
<row>
<value>4</value>
<value>5</value>
<value>6</value>
</row>
<row>
<value>7</value>
<value>8</value>
<value>9</value>
</row>
</matrix>

Using the dicttoxml Library

For quick, zero-configuration conversion, the third-party dicttoxml library handles lists and dictionaries automatically:

pip install dicttoxml
import dicttoxml
from xml.dom.minidom import parseString

data = ["Apple", "Banana", "Cherry", "Date"]

# Convert list to XML bytes
xml_bytes = dicttoxml.dicttoxml(data, custom_root="fruits", item_func=lambda x: "fruit")

# Pretty print the result
xml_pretty = parseString(xml_bytes).toprettyxml(indent=" ")
print(xml_pretty)

Output:

<?xml version="1.0" ?>
<fruits>
<fruit type="str">Apple</fruit>
<fruit type="str">Banana</fruit>
<fruit type="str">Cherry</fruit>
<fruit type="str">Date</fruit>
</fruits>
note

dicttoxml automatically adds type attributes to elements, which can be helpful for deserialization but may not be desired in all cases. You have less control over the output format compared to ElementTree.

Handling Special Characters

XML has reserved characters (<, >, &, ", ') that must be escaped in text content. The ElementTree module handles this escaping automatically:

import xml.etree.ElementTree as ET

items = ["Cookies & Cream", "Ben's Choice", 'Size: 5" x 3"', "Price < $10"]

root = ET.Element("items")
for item in items:
elem = ET.SubElement(root, "item")
elem.text = item

tree = ET.ElementTree(root)
ET.indent(tree, space=" ")
print(ET.tostring(root, encoding="unicode"))

Output:

<items>
<item>Cookies &amp; Cream</item>
<item>Ben's Choice</item>
<item>Size: 5" x 3"</item>
<item>Price &lt; $10</item>
</items>

Special characters are automatically escaped (& becomes &amp;, < becomes &lt;), ensuring the output is always valid XML. You never need to escape these characters manually when using ElementTree.

Quick Comparison of Methods

MethodBuilt-inPretty PrintEase of UseBest For
xml.etree.ElementTreeYesYes (Python 3.9+)EasyGeneral use, production code
xml.dom.minidomYesYes (all versions)VerboseWhen DOM API or pre-3.9 pretty print is needed
dicttoxmlNo (pip install)Via minidomVery easyQuick, automatic conversion

Conclusion

Converting Python lists to XML can be accomplished with several approaches depending on your requirements:

  • xml.etree.ElementTree is the recommended built-in solution for most projects. It is efficient, handles special characters automatically, and provides clean pretty printing with ET.indent() in Python 3.9+.
  • xml.dom.minidom provides a DOM-based interface with built-in pretty printing across all Python 3 versions, though its API is more verbose.
  • dicttoxml offers zero-configuration automatic conversion for quick tasks when you do not need fine-grained control over the output format.

For most projects, ElementTree provides the best balance of simplicity, control, and performance. Building a reusable conversion function like the list_to_xml() example above ensures consistent XML generation across your codebase regardless of the input data structure.