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