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 structureResulting 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 namemerged into an array — the single most important rule of XML-to-JSON
an element containing child elementsbecomes a nested object
comments, processing instructionsgenerally 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 two item elements yield an array.
  • The consequence is that downstream code must handle both types, and a single item.length will 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

SymptomCause
parsererror / parse failurean unclosed tag, multiple root elements, or a character & not escaped to &amp;
Chinese turns to garbagethe raw file is not UTF-8, or the <?xml encoding="..."?> declaration disagrees with the actual bytes
part of the content is missingthe content was wrapped in <![CDATA[...]]>, which some handling ignores
tag names do not line upXML 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.