Skip to content
jsonbeautifiers
English

XML to JSON

Attributes, CDATA and entities handled, with mismatched tags named precisely.

XML
JSON

Nothing you paste leaves your browser. The connect-src allowlist makes that a browser guarantee rather than a promise. Check it yourself

Convert XML to JSON, with attributes, CDATA sections and entity references handled, and malformed XML reported precisely rather than generically.

XML carries more structure than JSON can hold, so this direction is lossy in named ways. Every one of them is reported in the notes when it applies to your document.

Errors that name the actual problem

The browser has an XML parser built in, but its error reporting is a localised HTML fragment that cannot be read reliably. This page uses its own parser so the diagnostics match the quality of the JSON side.

Mismatched tags
Names both the closing tag and the element it should have closed. XML nests strictly, unlike HTML.
Unclosed elements
Lists everything still open when the document ended.
A second root element
An XML document has exactly one. This is a common result of concatenating two files.
HTML habits
A valueless attribute such as checked, or an unquoted attribute value. Both are legal HTML and neither is legal XML.
Unterminated comments and CDATA
Reported at the position where the section opened.

What JSON cannot represent

Mixed content
An element with both text and child elements. JSON has no way to keep the text ordered relative to the children, so the text is collected into a single #text key and the conversion says so.
Element order across different names
Repeated siblings become an array and keep their order, but the relative order of differently named siblings is lost, because JSON object keys carry no order.
Namespaces
Prefixes are kept as part of the name; the namespace declarations themselves become ordinary attributes.
One element against many
A list with a single element becomes a single value rather than an array of one, which is the classic source of downstream bugs. Turn on always use arrays to avoid it.

Types

XML is text. Everything is a string unless you turn on inference, and even then a value that would not survive a float64 round trip stays a string. This is the same policy as the CSV converter and for the same reason.

How to do this in code

Converting in code.

py Python
import xmltodict, json

data = xmltodict.parse(xml_text)
print(json.dumps(data, indent=2))

# force_list keeps single elements as arrays, which stops the
# classic "sometimes a list, sometimes an object" bug.
data = xmltodict.parse(xml_text, force_list={'item'})
js JavaScript
import { XMLParser } from 'fast-xml-parser';

const parser = new XMLParser({
  ignoreAttributes: false,
  attributeNamePrefix: '@',
  isArray: (name) => name === 'item',
});
const data = parser.parse(xmlText);
sh Shell
# xq, the XML front end to jq
xq . input.xml

# Or with Python, no extra install beyond xmltodict
python -c 'import sys,xmltodict,json; print(json.dumps(xmltodict.parse(sys.stdin.read()), indent=2))' < in.xml

Questions

Why is one of my lists not an array?
Because it had exactly one element, and a single child cannot be told apart from a list of one. Turn on always use arrays. This is worth doing whenever the output feeds code rather than a human, since it removes an entire class of bug.
What happened to my namespaces?
Prefixes survive as part of the key name and the xmlns declarations become ordinary attributes. JSON has no namespace concept, so the semantic relationship between them is lost.
Why does my HTML fail to parse?
HTML is not XML. Unclosed <br>, valueless attributes and unquoted values are all legal HTML and none of them are legal XML. For HTML you need an HTML parser, not this.