Convert XML to JSON

Drop an XML file here

or paste it below — .xml, .rss, .svg, .config

Conversion options

Paste XML or drop a file in and get JSON back, parsed by your browser's own XML engine. The difference is what happens to repeating elements: normally one item element becomes an object and two become an array, so the same feed produces two different shapes and the code reading it eventually breaks. Here an element that repeats stays a list everywhere, even in the file that happens to contain one of them, and the page reports every place the count changed. Nothing is uploaded.

How to convert XML to JSON

  1. Drop an .xml file into the box above, or paste the markup straight into the XML field. Nothing is uploaded either way.
  2. Leave Keep repeating elements as arrays ticked unless you specifically want the old count-based behaviour.
  3. If you know an element that will repeat in your next file but happens to appear once in this one, type its name into the arrays field.
  4. Press Convert to JSON and read the report before you copy the result. It names what the conversion could not carry across.

The problem this page exists for

XML has no way to mark a list. A purchase order with three line items and a purchase order with one line item are both perfectly valid, and they look the same to a parser except for how many times the element occurs. So a converter guesses from the count:

The XMLWhat converters give you
<items><item>A</item><item>B</item></items> {"items": {"item": ["A", "B"]}} — an array
<items><item>A</item></items> {"items": {"item": "A"}} — a string

Both outputs are defensible and the second one is a bug waiting for a quiet Tuesday. Code written against the first calls .item.map(), works for months, and then throws the day an order arrives with a single line. Nothing changed in the feed; the converter simply described the same structure two different ways.

Every converter we looked at documents this behaviour. None of them fixes it. Here, an element that repeats anywhere in the document is a list everywhere in the output, including under the parents where it occurs once — and if you know the shape of the data better than this particular file does, you can name the elements that must always be arrays.

Shape changes that are visible in one file

Sometimes the instability is provable without seeing a second file. If a document has one shelf holding two books and another shelf holding one, a count-based converter emits an array in the first and an object in the second — for the same element, in the same file. The report calls those out by name, because they are the clearest evidence that the output shape is an accident of the data rather than a property of the format.

What JSON cannot hold, and what we do about it

In the XMLWhat usually happensWhat happens here
An attribute and a child element with the same name Without a prefix one overwrites the other and a field vanishes Attributes are prefixed with @; the clash is named in the report
Two namespaces using the same local name Prefixes stripped, two different elements merged into one key Prefixes kept by default; if you strip them, every merge is listed
Text and child elements in the same element The text is silently dropped Kept under #text, and the paths are listed
Comments and processing instructions Dropped without mention Dropped — JSON has no equivalent — but counted
<![CDATA[...]]> Usually fine, occasionally kept as a nested wrapper Unwrapped to plain text, with the markup characters intact

Numbers are where data goes missing

XML values are all text, so converting them to JSON numbers is a decision rather than a translation. Two cases cost real data and neither announces itself:

  • Leading zeros. 00721 is a postcode, not the number 721. Convert it and the zeros are gone permanently.
  • Long whole numbers. JavaScript holds integers exactly only up to 9,007,199,254,740,991. Past that — most 17-digit order, account and barcode numbers — conversion changes the final digits: 9007199254740993 becomes 9007199254740992.

Both stay as text, and the page counts how many values were held back for that reason. You can also switch type conversion off entirely and receive every value as a string, which is what you want when the JSON is going straight into something that will parse it again.

Why a broken file gets an error rather than a result

XML is strict on purpose: an unclosed tag or a bare & makes a document not well-formed, and the specification says a parser must stop. This page uses the browser's own DOMParser, so it stops too, and shows the line and column where it gave up. Tools that promise to convert “even if your XML is not well-formed” are guessing at where the document should have ended — they return something that looks complete and is missing everything after the fault.

Next steps

Going back the other way is JSON to XML, which reads the @ prefix as attributes so a round trip keeps them where they belong. If the XML is really a table, XML to CSV turns it into rows and columns and tells you which element it treated as a record. And once you have JSON, JSON to CSV flattens it into a spreadsheet. The rest are on the data tools page.

Frequently asked questions

Why does my JSON change shape between two files from the same source?

Because XML has no way to say "this is a list". A converter looks at how many times an element appears and guesses: one occurrence becomes an object, two become an array. Export the same report on a quiet day and the list turns into a single object, so code that calls .map() on it throws. The fix is not in the XML, it is in the converter - here any element that repeats anywhere in the document is treated as a list everywhere, so a one-item list arrives as an array with one entry. You can also name extra elements by hand, for the ones your next file will have two of.

What happens to attributes?

They become keys prefixed with @ by default, so an item with id="7" gives "@id": "7" alongside the element's children. The prefix is not decoration: an element can legally carry an attribute and a child element with the same name, and without a prefix one silently overwrites the other. You can change the prefix to @_ or _ to match a library you already use, and the page tells you when it finds a name that exists both ways.

How are namespaces handled?

Prefixes are kept as part of the key, so a node in namespace a becomes "a:node". That is the safe default, because two namespaces can use the same local name for different things. If the prefixes are just noise in your document you can strip them - and if stripping merges two different elements into one key, the page says which ones, rather than letting half the data quietly disappear.

Will numbers and IDs survive the conversion?

Yes, when the guards do their job. Type conversion is optional, and while it is on, values with a leading zero such as 00721 stay text because turning them into 721 destroys a postcode, and whole numbers past 9007199254740991 stay text because JavaScript cannot hold them exactly and would change the final digits. The page counts how many values were deliberately kept as text.

What about comments, CDATA and processing instructions?

JSON has nowhere to put them. CDATA sections are unwrapped and their text is kept, because that is content. Comments and processing instructions are dropped, because they are not - but they are counted and reported, so you know the output is not a complete record of the file in the cases where that matters.

My element has text and child elements at the same time. What do I get?

That is mixed content, and it is the one XML shape JSON genuinely cannot hold. The text is kept under a #text key beside the children rather than being thrown away, and the page lists which paths had it. Most converters drop that text without a word.

Why does it fail with a line number instead of returning a result?

Because the XML is not well-formed - an unclosed tag, a bare ampersand, a second root element. XML is strict by design and your browser's parser refuses rather than guessing, so the error is shown with the line and column it stopped at, which is usually enough to find it. A converter that does its best with broken XML hands back output that looks fine and is missing everything after the problem.

Is my file uploaded?

No. The document is parsed and converted inside your browser tab with the same DOMParser that renders pages, so configuration files, exports and API responses never travel to a server. Turn your network off after the page loads and it still works.