Convert JSON to XML or XML to JSON in the page: keys become elements, - keys become attributes, repeated elements come back as arrays, and input that does not parse is reported with the position where the parser stopped instead of a broken result.
Runs locally in your browserJSON to XML turns a JSON object or array into an XML document; XML to JSON reads an XML document back as JSON. Both directions run in the page, so nothing you paste is uploaded, and the result is written to the panel under the buttons.
The two example buttons load the same small catalog in both formats: convert the JSON example and you get the XML example, convert that XML example back and you get the JSON example.
The document gets exactly one root element. A single top-level key becomes that element — {"user":{"name":"Ann"}} is written as <user><name>Ann</name></user> — while several keys, a top-level array and a single key that holds an array are wrapped in <root>; array items with no name of their own are written as <item>.
Inside an element a key becomes a child element and an array repeats its element once per item. A key that starts with - becomes an attribute and #text becomes the text of the element, so {"a":{"-x":"1","#text":"hi"}} is written as <a x="1">hi</a> — the shape the XML to JSON direction produces, which is what lets the two directions be chained. null and "" both become <name />.
Names are repaired rather than written broken: a space, < or & in a key, or a key that starts with a digit, is written with an underscore, and the status line reports how many names were changed. Markup inside a value is escaped, and quotes, line breaks and tabs in an attribute value are written as ", and 	 so the document stays well formed.
Attributes come back with a - prefix, an element that holds only text becomes a string, an element with children becomes an object, and a name that occurs more than once becomes an array: <r><i>1</i><i>2</i></r> becomes {"r":{"i":["1","2"]}} while a single <i> stays a string. XML carries no types, so values arrive as strings — 24.90 in XML is "24.90" in JSON.
An element with no content becomes an empty string, text inside an element is kept exactly as written, spaces and line breaks included, and the indentation between elements is ignored. Comments are skipped, CDATA sections are read as text, and text that shares an element with child elements is collected into a #text key.
The conversion runs in the page: with the network blocked it still works and sends no request, so a document that is not allowed to leave your machine can be converted here. Results up to 120,000 characters are syntax highlighted and larger results are printed as plain text — 1,000 rows (45 KB of JSON into 99 KB of XML) take about 0.8 seconds with highlighting, while 5,000 rows (233 KB into 503 KB, and back to 618 KB of JSON) take about 0.2 seconds in total, measured in Chrome on this page.
This is a format converter, not a schema tool: there is no XSD or DTD validation, no namespace handling (a colon in a name is written as an underscore) and no type inference. Documents nested thousands of levels deep are refused with a message instead of leaving a partial document on screen.