XML to JSON
Attributes, CDATA and entities handled, with mismatched tags named precisely.
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.