Convert XML to JSON and back with clear rules for attributes, text and repeated elements. Nothing is uploaded.
To convert XML to JSON, each element becomes a key, each attribute becomes a key that starts with @, and text becomes a string, so a price element with the attribute currency set to USD and the text 9.99 turns into {"price": {"@currency": "USD", "#text": "9.99"}}. The rules are fixed and listed here because XML has no single standard mapping to JSON. An element with only text is just that string. An element with attributes or child elements keeps its text under #text. An empty element, written as a self-closing tag, becomes null. Elements that repeat under one parent become an array, in document order, and Always use arrays for child elements makes every child an array so the shape never depends on how many there are. Namespace prefixes stay in the names, so xs:element and xmlns:xs are kept as written.
Text is trimmed at both ends. A CDATA section is kept as text with its content unchanged, so a CDATA section holding a < b && c becomes the string a < b && c. The five built-in entities (& < > " ') and numeric references such as © are decoded. When an element holds text on both sides of a child element, such as the words Read and first around a bold word, the text pieces are joined with a space into one #text and the order between text and elements is not kept. Comments and processing instructions are dropped, and a notice says so. Values stay strings unless you turn on Convert numbers and booleans, which changes only true, false and numbers that print back the same: 9.99 becomes a number, 1.50 and 007 stay text.
The reverse direction follows the same rules. A key starting with @ becomes an attribute, #text becomes the element's text, an array becomes repeated elements with the key's name, and null becomes an empty element. If the JSON has one top-level key, that key is the root element; otherwise everything is wrapped in the root name you set, which is root by default. Text and attribute values are escaped for & < > and quotes. A key that is not a valid XML name, such as one with a space or a leading digit, is changed to a valid one and a notice counts the changes. An empty list produces no elements, and a list inside a list becomes elements named item.
A DOCTYPE is skipped and never read. Entities it defines are not expanded and no file or address in it is fetched, so a document cannot pull in a local file or grow into a billion laughs expansion. A named entity that is not one of the five stays as written, for example © stays ©. Errors give the line and column, such as Line 4, column 3: the closing tag does not match the open tag. Up to 500,000 characters and 500 levels of nesting are handled. Numbers in JSON are read as JavaScript numbers, so integers beyond 9,007,199,254,740,991 lose precision. Everything runs in this tab.
Paste the XML, keep XML to JSON selected, and copy the result. A book element with the attribute id set to b1 and a title element holding Dune gives {"book": {"@id": "b1", "title": "Dune"}}. Errors name the line and column.
As keys that start with @, placed before the child elements, for example "@id": "b1". In the other direction a key starting with @ is written back as an attribute.
By default an element becomes an array only when it repeats, so one tag element is a string and two are a list. Turn on Always use arrays for child elements to get a list every time, which is easier to read from code.
Values stay strings unless Convert numbers and booleans is on. Even then, a value such as 1.50, 007 or 12345678901234567890 stays text, because turning it into a number would change how it prints.
No. A DOCTYPE is skipped, the entities it defines are not expanded, and nothing is fetched. This closes the XXE and entity expansion problems that DTD processing can cause.
No. The text is processed in your browser and not uploaded. The XML or JSON itself is never saved; only your option choices are kept on this device.