Runs on your device · Your file never leaves your device.
Paste or drop JSON and get an XML document with a declaration on top and one element per key. A document with a single top-level key uses it as the root element; anything else goes inside <root>. A list becomes repeated elements named after its key — "items": [..] gives several <items> elements — and a top-level list becomes <item> elements under <root>.
Keys that start with @ become attributes and a "#text" key becomes the element’s text — the shape the XML to JSON tool writes, so a document converted there comes back here as the same XML. Every other value is text inside its element, null becomes an empty element, and the document is indented two spaces per level. Keys that XML does not allow as names — starting with a digit, containing spaces or symbols — are sanitised with underscores so the result always parses.
Text is escaped correctly (&, <, > and, in attributes, quotes and line breaks); control characters, which XML 1.0 cannot hold at all, are removed. The encoding is UTF-8, and you see the first 200 lines before downloading. Nothing is uploaded.
Not for: Matching a specific XML schema (SOAP, RSS, an invoice standard) — the element names follow your JSON keys, not a schema.
A key that starts with @ becomes an attribute and a "#text" key becomes the element's text, so {"item": {"@id": 3, "#text": "A"}} gives <item id="3">A</item>. When the document has a single top-level key, that key is the root element; otherwise everything goes inside <root>.
A character that XML does not allow in a name becomes an underscore, and a name that starts with a character not allowed first, such as a digit, gets one in front: "1st place" becomes <_1st_place>. A colon is kept only when its prefix is declared higher up, as in "@xmlns:soap"; an undeclared "soap:Body" becomes <soap_Body>, because no namespace-aware parser would read it otherwise. Letters from any script are allowed, so a key such as "اسم" or "名前" stays as written.
Every value is written as text, and numbers exactly as the JSON has them: 1.0 stays 1.0 and 12345678901234567890 keeps every digit. null and an empty object both become an empty element such as <note/>, and an empty list writes nothing at all, so the XML cannot tell these three apart.
Control characters, codes below 32 other than tab, line feed and carriage return, cannot be written in XML 1.0 at all, not even as a number such as , so they are removed. A carriage return is written as so a parser keeps it. In attribute values, quotes, tabs and line breaks are also written as references, because a parser would otherwise turn them into spaces.
Repeated elements can express only one level of list. "m": [[1, 2], [3]] becomes three <m> elements holding 1, 2 and 3, and the fact that 1 and 2 belonged together is gone. A top-level list behaves the same way: [1, [3, 4]] gives three <item> elements. If the grouping matters, wrap each inner list in an object first: [{"values": [1, 2]}, {"values": [3]}] gives two <item> elements, each holding its own <values>.
A document that went through /xml-to-json comes back as the same elements, attributes, namespace prefixes and text, with no extra wrapper around it. What the JSON never held does not come back: comments and the DOCTYPE, the position of text between child elements, and the order between elements of different names, which come back grouped by name. If type detection was on in /xml-to-json, a value such as TRUE comes back as true; switch detection off there for a word-for-word round trip.
This page in other languages: العربية · Deutsch · Français · Español · Русский · Português · 中文 · हिन्दी · Türkçe · עברית · فارسی · اردو · Bahasa Indonesia · বাংলা