What this tool does
It finds the repeated element and makes each occurrence a row.
<orders>
<order id="1"><customer>Ada</customer><total>42</total></order>
<order id="2"><customer>Alan</customer><total>17</total></order>
</orders>
customer,total,id
Ada,42,1
Alan,17,2
Single-key wrappers are walked through, so <orders><order>… needs no configuration. A wrapper carrying its own attribute — <orders count="2"> — is walked through too: that attribute describes the collection, not a row, so it does not become a column. An attribute on a row does.
Attributes are columns
An identifier that lives in an attribute is data like any other. @_id becomes the column id.
The prefix is kept in exactly one case: when a child element already carries that name. <row id="1"><id>x</id></row> gives two columns, id and @_id, because they hold two different things and merging them would make one of them disappear. A toggle drops attributes entirely if your table should come from the elements alone.
One row is a table
An export with a single record converts like any other. That is worth saying because it did not use to: XML-to-JSON turns a non-repeated element into an object rather than an array, and requiring the array rejected a perfectly ordinary document.
A root element containing nothing but text is still refused — one value is not a table, and pretending otherwise would help nobody.
Rows that do not match
The header is the union of everything seen, in first-seen order. A row missing a column gets an empty cell:
<r><row><a>1</a></row><row><a>2</a><b>3</b></row></r>
a,b
1,
2,3
An irregular export is normal. Dropping the extra column, or the row that lacks it, would lose data to tidiness.
What a cell cannot hold
A cell holds one value. When an element contains a subtree, that subtree is written as JSON inside the cell rather than spread across invented column names. It is ugly and it is honest: nothing is lost, and you can see exactly what was there.
Private by design
Everything runs locally in your browser with JavaScript. Your data is never uploaded, which makes the tool safe for sensitive content, and it keeps working offline.