How JSON maps to XML
| JSON | XML |
|---|---|
Object with one key{"note": {"to": "Ana"}} |
<note><to>Ana</to></note> |
Key starting with @{"book": {"@id": "b1", "title": "XML"}} |
<book id="b1"><title>XML</title></book> |
#text next to attributes{"price": {"@currency": "EUR", "#text": "9.50"}} |
<price currency="EUR">9.50</price> |
Array{"list": {"item": ["a", "b"]}} |
<list><item>a</item><item>b</item></list> |
null and empty string{"user": {"middleName": null}} |
<user><middleName/></user> |
Key that isn’t a valid XML name{"order": {"first name": "Ana", "2fa": true}} |
<order><first_name>Ana</first_name><_2fa>true</_2fa></order> |
JSON to XML in code
# pip install xmltodict (same @attribute / #text convention)
import json, xmltodict
xml = xmltodict.unparse(json.loads(data), pretty=True)
import { XMLBuilder } from 'fast-xml-parser';
const builder = new XMLBuilder({ ignoreAttributes: false, attributeNamePrefix: '@', textNodeName: '#text', format: true });
const xml = builder.build(JSON.parse(data));
Going the other way? Use XML to JSON. To query the result, try the XPath tester, or tidy existing XML with the XML formatter.
Frequently asked questions
How do I make a value an XML attribute?
Start its key with @: {"book": {"@id": "b1"}} becomes <book id="b1"/>. Text that should sit next to attributes goes in a #text key. These are the same conventions the XML to JSON converter uses, so you can convert XML to JSON, edit it, and convert it back. Change or clear the prefix if your JSON uses another convention, such as _ or $.
How are JSON arrays converted?
XML has no arrays, so each item becomes a repeated element with the array’s key as its name: {"tag": ["a", "b"]} becomes <tag>a</tag><tag>b</tag>. A top-level array is wrapped in a root element, with each item in an <item> element; both names can be changed.
What happens to keys that aren’t valid XML names?
XML element names can’t contain spaces or most punctuation, can’t start with a digit, and can’t start with “xml”. Such keys are changed (spaces and invalid characters become _, and an _ is added in front where needed), and every renamed key is listed under the tool, so nothing changes silently.
Are numbers kept exactly?
Yes. Numbers are copied from your JSON as written, so 9007199254740993, 1.10 and 1e-7 appear in the XML unchanged. A converter that runs JSON.parse first would turn the first into 9007199254740992 and the second into 1.1.
Is the output valid XML?
Yes: &, < and > are escaped in text, quotes and line breaks are escaped in attributes, and control characters that XML 1.0 doesn’t allow at all are removed. With one root element and valid names, any XML parser can read the result.