Convert XML to CSV — Free, Private, In-Browser
XML to CSV here is a flattening from a record-oriented document into a table, not a general XML transform. dataeng.tools finds the repeating element in your file — the set of same-tag siblings that recur, like <row> inside <rows> or <item> inside an RSS <channel> — and treats each occurrence as one row. That is the natural fit for record-list XML: RSS/Atom items, SOAP response bodies, and database exports that carry many uniform entries. Each record becomes a line in the CSV, with a header row derived from the fields seen across the records. If your XML is genuinely a list of like records, it lands cleanly as a table; if it is a deeply nested, one-of-a-kind document, it will not.
Inside each record, the mapping to columns follows a few consistent rules. Attributes become columns prefixed with @, so <row id="7"> gives you an @id column holding 7. A child element that carries only text becomes a column named for its tag, with that text as the value. Structure that has no flat equivalent — a repeated child tag, or a nested element with its own children — can't fit one CSV cell, so it collapses to JSON-ish text inside the field. The point to internalize is that CSV and XML are both untyped: every value arrives as a string, and there is nothing to cast on the way out. Numeric IDs, booleans, and dates all land as text, and downstream code has to re-infer the types.
The limitation worth stating plainly: only the repeating-record shape is captured, not arbitrary document structure. Feed-level metadata that sits beside the records but does not itself repeat — an RSS <channel> title, a SOAP envelope header, a top-level <generated_at> — is not folded into the CSV, because the converter is hunting for the record list, not serializing the whole tree. The column set is the union of fields seen across records, so a record missing a field just gets an empty cell there; a header row is included and NULLs are written as empty fields. Everything runs locally in your browser — the file is parsed and converted on your machine and is never uploaded.
Drop a file or click to browse
Drop a XML file — processed locally, never uploaded
Frequently asked questions
- How does it decide what becomes a row versus a column?
- It scans for the shallowest set of repeated same-tag sibling elements and makes each occurrence a row — <row> under <rows>, or <item> under an RSS <channel>. Within a record, attributes and text-carrying child elements become the columns (attributes prefixed with @). If nothing in the document repeats, you get a single row so you still get valid CSV back.
- What happens to nested or repeated child elements?
- They have no flat CSV equivalent, so they're serialized to JSON-ish text inside a single cell rather than exploded into more columns. A record with a repeated <tag> or a nested element that has its own children keeps that structure as text in one field. If you need it broken out into real columns, convert to JSON first and reshape from there.
- Why isn't my feed's header or metadata in the CSV?
- Only the repeating record list is captured, not the surrounding document. Non-repeating siblings like an RSS <channel> title, a SOAP envelope header, or a top-level <generated_at> sit outside the record set, so they aren't included. The output is the table of records, not a full-tree transform — if you need that metadata, pull it separately.
- Is my file uploaded anywhere?
- No. The XML→CSV conversion runs entirely in your browser via DuckDB-WASM. Your file never leaves your device.
- How large a file can I convert?
- It's bounded by your browser's available memory rather than any server limit — files in the hundreds of MB are routine. DuckDB runs single-threaded here, so very large files just take a little longer.
- Do I need an account?
- No — it's free and requires no sign-up.