FormatterHQ

XML to CSV Converter

Extract the repeating records from an XML file into CSV rows for Excel, Google Sheets or a database import. Attributes become columns too.

Input XML
Output CSV
Ready.

How to use the XML to CSV Converter

  1. Paste XML into the input editor, upload an .xml file, use Load URL, or click Sample.
  2. Adjust the Attribute prefix, Delimiter, Include header row, Flatten nested objects and Quote all fields as needed.
  3. Click Convert to CSV; the status bar shows the number of records.
  4. Copy the CSV or Download it.

Turn XML records into an XML to CSV table

Most XML exports are lists in disguise: a catalog of <book> elements, a feed of <order> entries, a set of <row> records from a legacy system. This XML to CSV converter finds that repeating element, turns every occurrence into a row, and turns attributes and child elements into columns, so you can open the data in any spreadsheet or load it into a database.

Example

<catalog>
  <book id="bk101" lang="en">
    <author>Gambardella, Matthew</author>
    <title>XML Developer's Guide</title>
    <price>44.95</price>
  </book>
  <book id="bk102" lang="en">
    <author>Ralls, Kim</author>
    <title>Midnight Rain</title>
    <price>5.95</price>
  </book>
</catalog>

Output:

@id,@lang,author,title,price
bk101,en,"Gambardella, Matthew",XML Developer's Guide,44.95
bk102,en,"Ralls, Kim",Midnight Rain,5.95

Author names contain a comma, so they are quoted automatically; everything else is written as is. The XML declaration, comments and the <catalog> wrapper do not appear in the table because they are not records.

How the rows are found

The converter parses the XML into a data tree, then walks down through wrapper elements that contain only one thing (such as <catalog>) until it reaches a list of repeated elements. Each element in that list becomes a row. Columns are collected from all rows in the order they first appear, so if only some books have a <discount> element, the column still exists and the other rows leave it empty.

Columns from attributes and nested elements

  • Attributes become columns named with the Attribute prefix, @id by default. Clear the prefix to get plain id headers.
  • Nested elements are flattened with dots when Flatten nested objects is on: <address><city> becomes an address.city column.
  • Repeated child elements get numbered columns, like sku.0 and sku.1.
  • With flattening off, nested content is written into one cell as JSON text.

A pitfall: one child versus many

XML does not mark which elements are lists. Consider two orders where the first has one <sku> and the second has two:

<orders>
  <order id="1"><sku>A</sku></order>
  <order id="2"><sku>B</sku><sku>C</sku></order>
</orders>
@id,sku,sku.0,sku.1
1,A,,
2,,B,C

The single sku lands in its own column while the repeated ones are numbered. If your data mixes single and repeated children like this, merge the columns in your spreadsheet, or convert with flattening off to keep each order's SKUs together in one cell.

Delimiter, quoting and typing

  • Delimiter – comma, semicolon, pipe or tab. Semicolons are often easier for spreadsheet apps in regions that use a decimal comma.
  • Quote all fields – wraps every value in quotes, which some strict importers prefer.
  • Detect numbers & booleans – mainly matters for other output formats; in CSV every value is text anyway, but leading zeros are always preserved.
  • Include header row – turn it off to append rows to an existing file.

Related tools

Need a real workbook instead of text? Use XML to Excel. To inspect the structure before converting, try the XML viewer, and to check the CSV afterwards, the CSV viewer shows it as a table.

Privacy

The XML is converted in your browser and not uploaded. Only Load URL and Save & Share send content to our server.

Convert XML to CSV in Python

Parse the document with xml.etree.ElementTree, loop over the repeating element and write one row per record with csv.writer. Attributes are read with .get() and child elements with .findtext(). The common crash is record.find("price").text on a record that has no price: find() returns None and the script stops with an AttributeError. findtext("price", "") returns an empty string instead, which keeps the columns aligned.

import csv
import sys
import xml.etree.ElementTree as ET

data = """<catalog>
  <book id="b1"><title>XML Guide</title><price>29.99</price></book>
  <book id="b2"><title>Tea &amp; Code</title></book>
</catalog>"""
root = ET.fromstring(data)

writer = csv.writer(sys.stdout, lineterminator="\n")
writer.writerow(["id", "title", "price"])
for book in root.iter("book"):
    writer.writerow([book.get("id"), book.findtext("title", ""), book.findtext("price", "")])

Paste the XML into the converter above to see which columns it finds before you hard-code them in a script.

Frequently asked questions

Which XML element becomes a row?
The converter descends through single wrapper elements until it finds a list of repeated elements, and each of those becomes a row. For , every book is a row.
How do I remove the @ from attribute column names?
Clear the Attribute prefix option. Attributes then become plain column names such as id and lang.
Why do I get columns like sku.0 and sku.1?
A child element repeats inside a record, and flattening gives each occurrence its own numbered column. Turn off Flatten nested objects to keep them together as JSON text in a single cell.
Can I convert a large XML file?
Yes, within your browser memory. The conversion runs locally, so very large files depend on your device; files of a few megabytes are usually no problem.

Last updated October 3, 2026

Related tools