Convert XML to CSV

Runs on your device · Your file never leaves your device.

Drop an XML file of repeated records — <records><record>…</record>…</records>, an RSS feed, an export from a database — and get a CSV with one row per record. The document is read by the browser’s XML parser, then the longest list of repeated elements is found automatically, whatever wraps it — an attribute on the wrapper, or a feed’s own title and link beside its items — and the result line names the list it used.

Each record is flattened the same way as in the JSON to CSV tool: nested elements become dot-separated columns (address.city), attributes become @-prefixed columns (@id), repeated inner elements with children of their own get numbered columns (line.0.sku), repeated text elements are joined with semicolons (a;b), and the header row is the union of every column found. Values are written exactly as the XML has them. Fields with commas, quotes or line breaks are quoted to RFC 4180.

The CSV is UTF-8 with an optional byte-order mark for Excel, you choose the separator, and you can preview the first 200 lines before downloading. Nothing is uploaded.

How to convert XML to CSV

  1. Drop an XML file, or paste XML into the box.
  2. Pick the output separator and whether to add the Excel BOM.
  3. Press Convert to CSV and check the preview.
  4. Download the .csv.

Supported formats and limits

Input
XML (.xml) — a file or pasted text, read in the encoding it declares
Output
CSV, RFC 4180, UTF-8, optional BOM
Rows
The longest list of repeated elements
Nesting
Child elements → dot columns; attributes → @columns
Where it runs
In your browser; nothing uploaded

Not for: Documents with several lists of records — only the longest becomes rows; for another, convert to JSON, copy that list and convert it with JSON to CSV.

How the rows are found

The rows are the longest list of repeated elements anywhere below the root, whatever wraps it. <records count="2"><record>…</record><record>…</record></records> gives one row per <record>, even though the wrapper has an attribute. An RSS feed gives one row per <item>, with columns such as title, link and pubDate, even though the channel's own title and link sit beside the items. The line under the result names the list used, for example rss.channel.item.

Values beside that list, like the feed's own title, are not part of any record and are left out. When a document holds several lists of records, only the longest becomes rows. For another one, convert the file with /xml-to-json, copy that list from its [ to its ], paste it into /json-to-csv and convert.

A file with only one record

With no repeated element, the single record is the one row, and its columns are its own field names: <records><record><name>Ali</name><city>Cairo</city></record></records> gives the columns name and city. A file that sometimes holds one record and sometimes many therefore keeps the same header, which matters when another program reads the columns by name.

How values are written

Values are written exactly as the XML has them: 1.50 stays 1.50, TRUE stays TRUE, and an element holding NULL gives the text NULL, while an empty element gives an empty cell. 007 keeps its zeros, and dates stay as written. A value that begins with =, +, - or @ gets an apostrophe in front, as on /json-to-csv, so a spreadsheet does not run it as a formula.

Repeated child elements that hold only text are joined with semicolons in one cell, so two <tag> elements give a;b. Repeated child elements with children of their own get numbered columns, such as line.0.sku and line.1.sku. Namespace prefixes stay in the column names, as in soap:Body.price. Text that sits beside child elements goes into a #text column without its position among them. The file is read in the encoding its first line declares.

Frequently asked questions

Are my files uploaded to a server?
No. This conversion runs inside your browser using your own device’s processing power, and the file is not uploaded. Once a tool has been used once (video, text recognition and background removal download their engine from this site the first time), it keeps working when your connection drops.
How does it know which elements are the rows?
It takes the longest list of repeated elements below the root — so <records><record>…</record></records> gives one row per <record>, and an RSS feed one row per <item>. Values beside that list, such as a feed’s own title, are left out. With no repeated element, the single record becomes one row with its own field names as columns.
Where do attributes go?
Into columns prefixed with @, so <record id="3"> produces a column named @id. Text beside child elements goes into a #text column.
Will Excel open it correctly?
Yes. The "Add a BOM for Excel" switch (on by default) writes the marker Excel needs to recognise UTF-8, so Arabic, accents and symbols display correctly.

Related tools

More in Spreadsheets & data

This page in other languages: العربية · Deutsch · Français · Español · Русский · Português · 中文 · हिन्दी · Türkçe · עברית · فارسی · اردو · Bahasa Indonesia · বাংলা