XML ⇄ JSON
Convert XML to JSON with the browser built-in parser
XML to JSON: How Attributes, Text Nodes and Repeated Elements Are Handled
It uses the browser's built-in parser
This tool reads XML with the browser's native parser (DOMParser) rather than hand-rolled regular expressions or string splitting. This matters because a hand-written XML parser is almost always wrong — entity references, CDATA, namespaces, the various ways attribute quotes are written, and self-closing tags will each break string handling at some boundary.
The cost is that the browser parser demands strictly valid XML: tags must close, there must be exactly one root element, case matters, and special characters must be escaped. A tag like <br> that is legal in HTML is an error in XML. HTML is not XML, so dropping an HTML fragment in will usually be rejected on purpose — accepting it would hand you a silently malformed result.
Handling attributes and text nodes
| XML structure | Resulting JSON form |
|---|---|
<name>Bob</name> | {"name":"Bob"} — a pure-text element becomes a string value |
<user id="7">Bob</user> | attribute id and text Bob must both be expressed, usually by placing the text under a约定 key such as #text while the attribute becomes a sibling key |
| repeated elements with the same name | merged into an array — the single most important rule of XML-to-JSON |
| an element containing child elements | becomes a nested object |
| comments, processing instructions | generally ignored |
Note the second row: an XML attribute and a child element land on the same level in JSON, which opens the door to a name collision — when an element has both an attribute id and a child <id>, the two clash on the same key. Such structures need an extra convention from the converter (a prefix, an underscore, and so on), and different tools handle it differently.
The single-value-versus-array ambiguity reappears
This is a problem in both JSON-to-XML and XML-to-JSON directions; going from XML to JSON it shows up as: when there is only one element of a name, should it be emitted as an array?
- If you decide purely by actual occurrence count, then
<item>1</item>yields{"item":"1"}(a string), and only twoitemelements yield an array. - The consequence is that downstream code must handle both types, and a single
item.lengthwill throw when there is only one element.
The robust move is to normalize downstream (for example, always wrapping with [].concat(value)), or to force certain paths to arrays at parse time based on a known schema. The tool itself cannot decide for you, so confirm the shape of the target field before you write code against it.
A failure-reference table
| Symptom | Cause |
|---|---|
parsererror / parse failure | an unclosed tag, multiple root elements, or a character & not escaped to & |
| Chinese turns to garbage | the raw file is not UTF-8, or the <?xml encoding="..."?> declaration disagrees with the actual bytes |
| part of the content is missing | the content was wrapped in <![CDATA[...]]>, which some handling ignores |
| tag names do not line up | XML is case-sensitive: <Name> and <name> are two different elements |
All parsing happens locally in your browser, so the XML returned by an API is never uploaded.
FAQ
Is there information loss during conversion?
Details such as XML comments, processing instructions and CDATA boundaries are lost; only elements, attributes and text are kept. That is enough for most data conversions.
Where did the attributes go?
They are collected into the @attributes object. This tool does not read that field when generating XML back, so handle it yourself if needed.