A Column Called "Total (EUR)" Cannot Be an XML Element Name
Published 9/15/2026 · 4 min read · File tools
Daniel Okonkwo — Front-end developer and tech writer at OneKitly
Web performance · File formats
Checked against 3 sources
Both exports read the first row as the field names and both then have to obey their own format's rules. JSON has almost none: a key can be any string, so a column headed Total (EUR) becomes the key "Total (EUR)" verbatim, and an unlabelled column becomes the key "" — awkward but faithful. XML has strict rules about names, and the header text usually breaks them. Measured on a four-column sheet: Produit stays Produit, Total (EUR) becomes Total_, 2026 ventes becomes _ventes because a name cannot start with a digit, and an empty header becomes column4. Nothing is dropped — every character that cannot appear in a name is folded into an underscore rather than deleted — but two different headers can normalise to the same element name, and that is worth checking before you feed the result to something that expects them distinct. The values themselves are escaped rather than altered, so an ampersand or an angle bracket in a cell survives the trip intact.
JSON takes your header text as a key exactly as written. XML cannot — its names may not hold spaces, parentheses or a leading digit — so they are normalised, and knowing how prevents a surprise downstream.
The blank row that only some formats emit
A sheet with a wholly blank row in the middle exports differently depending on the shape of the target. The row-shaped formats keep it: the CSV of a four-column sheet with one blank row contains a line reading three commas, and the TSV contains three tabs — because a row is a row and the format has no concept of an absent record. The object-shaped ones drop it: JSON emitted two objects for three data rows in the same test. XML is row-shaped by construction and would naturally keep it, which would have made the same file disagree with itself between two exports of the same tool. It drops the blank row instead, so JSON and XML agree.
Which target for which consumer
JSON when a script or an API is going to read it, because keys survive verbatim and a reader can address a column by its real name. XML when the consumer is an older system, an enterprise integration or anything that validates against a schema — and check the element names against that schema first, since normalisation may not produce what it expects. TSV when the destination is a database load or a shell pipeline: a tab is far less likely to appear inside a cell than a comma, so a tab-separated file needs less quoting and breaks less often. HTML when someone just needs to look at the table in a browser or paste it into a document.
| Header in the sheet | JSON key | XML element |
|---|---|---|
| Produit | "Produit" | <Produit> |
| Total (EUR) | "Total (EUR)" | <Total_> |
| 2026 ventes | "2026 ventes" | <_ventes> — no leading digit allowed |
| (no header) | "" | <column4> |
Frequently asked questions
- What if two headers normalise to the same element name?
- You get two elements with the same name inside each row, which is legal XML and usually not what a consumer wants. "Total (EUR)" and "Total (£)" both become Total_, for instance. Rename the columns in the sheet before converting — it is the only place the ambiguity can be resolved, since by the time the XML exists the original headers are gone.
- Are accented characters safe in either format?
- In values, yes — both are written as UTF-8 and the XML declares it in its prologue. In XML element names the rules are looser than they look: a name may contain accented letters, so a header reading Quantité would be a legal element. This converter is stricter than the specification and folds anything outside the plain Latin range into an underscore, which is the conservative choice for consumers that are themselves stricter than the specification, and there are many of them.
- Can I get one file per sheet instead of per workbook?
- Split the workbook first, then convert each piece — the split writes one .xlsx per sheet and the converters take one sheet at a time, so that route gives you exactly one output per tab with the names carried through. Converting a multi-sheet workbook directly gives you the first sheet, which is right for the common case of a workbook that is really one table.
Articles you may find interesting
All guides →Related tools
Sources
Spotted a mistake in this article?