How to Convert CSV to XML

Legacy import formats, .NET config, enterprise feeds — plenty of systems still ask for XML when your data starts life as a spreadsheet export. Here's the conversion without hand-building tags.

Option 1: The Transmute CLI (free)

Given people.csv:

name,age,city
Alice,32,Aarhus
Bob,25,Odense
$ transmute people.csv --output xml
<?xml version="1.0" encoding="UTF-8"?>
<data>
  <item>
    <name>Alice</name>
    <age>32</age>
    <city>Aarhus</city>
  </item>
  ...
</data>

Because transformation happens before serialization, you can filter and reshape on the way through:

$ transmute people.csv     --pipe '[{"op":"filter","expr":"item.age > 26"}]'     --output xml
<?xml version="1.0" encoding="UTF-8"?>
<data>
  <item>
    <name>Alice</name>
    <age>32</age>
    <city>Aarhus</city>
  </item>
</data>

Option 2: Python

import csv
from xml.etree.ElementTree import Element, tostring

root = Element("data")
for row in csv.DictReader(open("people.csv", newline="")):
    item = Element("item")
    for k, v in row.items():
        child = Element(k)
        child.text = v
        item.append(child)
    root.append(item)
print(tostring(root, encoding="unicode"))

Standard library only — but note it does not escape invalid tag names. A header like first name (with a space) produces broken XML unless you sanitize keys yourself.

Things that bite people

  • Tag naming. Column headers become element names: no spaces, can't start with a digit. Rename columns first ({"op":"rename",...}) if needed.
  • Escaping. Values containing & or < must be escaped — always use a serializer.
  • Types. CSV has no types, so everything arrives as text in the XML too. Decide downstream whether <age>32</age> needs casting.