XML ↔ JSON Converter

XML Input
JSON Output

How to Convert XML to JSON

Paste XML into the left panel and the JSON appears as you type. Parsing uses your browser's own XML parser — the same one that handles XHTML and SVG — so it validates well-formedness properly and reports the line where a document breaks, rather than accepting something malformed and producing quiet nonsense.

Everything runs locally. Your document is never uploaded, logged, or sent to a server, which matters because the XML developers most often need to convert is a SOAP response or a partner feed containing credentials, order records, or personal data.

The Mapping Convention

XML and JSON do not describe the same shape of data, so every converter has to invent a convention. This one is stated up front and applied without exception:

XMLJSON
Attribute id="bk101""@id": "bk101"
Element with only textThe string itself
Element with text and attributes or children"#text" alongside the other keys
A tag appearing more than onceAn array
Empty element <a/>null
<![CDATA[...]]>Merged into the element's text
XML in
<book id="bk101">
  <title>XML Guide</title>
  <price>44.95</price>
</book>
JSON out
{
  "book": {
    "@id": "bk101",
    "title": "XML Guide",
    "price": "44.95"
  }
}

The @ prefix exists because XML has two ways to attach a value to an element and JSON has one. Without it, an attribute named title and a child element named title would collide. The prefix keeps them distinct and makes the conversion reversible — switch to JSON → XML and any key beginning with @ becomes an attribute again.

Three Things That Make XML to JSON Genuinely Hard

1. Everything is a string, and no converter can know otherwise. <price>44.95</price> becomes "44.95", not 44.95. This is not a limitation of the tool — XML has no type system at all. Types live in an external XSD schema that is not part of the document, so a converter reading the document alone has nothing to work from. Converters that guess will eventually turn a product code like 0012 into 12. Cast on your side, where you know the schema.
2. One item and many items produce different shapes. A tag repeated twice becomes an array; the same tag appearing once stays a plain object. So an order with two line items gives you items.item[0], and an order with one gives you items.item — and code written against the first crashes on the second. This is the single most common bug in XML-to-JSON pipelines. Defend against it by normalising on read: const list = [].concat(parsed.items.item ?? []).
3. Comments, processing instructions, and the DTD are dropped. JSON has nowhere to put them. The XML declaration is regenerated on the way back rather than preserved, and a DOCTYPE is not carried across. If the document is a contract with an external system, keep the XML as the source of truth and treat the JSON as a view of it.

Namespaces

Namespace-qualified tags keep their prefix exactly as written: <soap:Envelope> becomes the key "soap:Envelope", and the declaration itself survives as the attribute key "@xmlns:soap". Nothing is resolved or rewritten, so a round trip through JSON and back produces a document with the same prefixes it started with.

This is the pragmatic choice rather than the theoretically correct one. Namespace prefixes are arbitrary labels — two documents using soap: and s: for the same namespace URI are equivalent to a validating parser but produce different JSON keys here. If you are consuming feeds from multiple vendors, match on the local name rather than the full prefixed key.

Converting JSON to XML

Switch direction and the convention runs backwards: @ keys become attributes, #text becomes the element's text content, arrays become repeated tags, and null becomes a self-closing element. Output is indented two spaces and carries an XML declaration.

A JSON object with exactly one top-level key uses that key as the root element, since XML permits exactly one. Several top-level keys are wrapped in a <root> element instead, because there is no other legal option.

Element names are validated rather than silently repaired. XML names cannot contain spaces and must begin with a letter or underscore, so a key like "first name" is reported as an error instead of being quietly rewritten to first_name — a rename would produce a document that no longer matches the schema it was headed for, and you would find out much later.

Escaping is handled for you, and only where the specification requires it: &, <, and > are escaped in element text, and attribute values additionally escape the double quote that would otherwise close them. A quote or apostrophe sitting in ordinary text is left alone, because escaping it would be noise rather than correctness. A document converted to JSON and straight back comes out byte-for-byte identical, entities included.

Why This Conversion Still Comes Up

XML was declared legacy years ago and remains everywhere it was already installed. Three cases account for most conversions.

SOAP and enterprise APIs. Banking, insurance, logistics, government, and healthcare integrations are overwhelmingly SOAP, and they are not being rewritten. Converting the envelope to JSON at the edge lets the rest of your codebase work in one format. The credentials in those envelopes are exactly why a converter that uploads your payload is the wrong tool.

RSS, Atom, and sitemaps. Feed formats are XML by specification. Anything that ingests feeds — readers, aggregators, monitoring — converts them on the way in.

Configuration in older toolchains. Maven pom.xml, Android manifests, .NET web.config, and Ant build files are XML. Converting to JSON makes them scriptable with ordinary tooling; if you are migrating that config to a modern format, our YAML ↔ JSON converter is the second half of the trip, since most current toolchains expect YAML.

Checking the Result

XML documents nest far more deeply than most JSON, and a converted SOAP response frequently arrives six or seven levels down inside envelope and body wrappers. Paste the output into our JSON formatter and validator — its depth and key counts tell you immediately whether you are looking at the payload or at the envelope wrapped around it. If the result is a list of records headed for a spreadsheet, JSON ↔ CSV will flatten it into columns.

Integrating with a legacy XML API? Uptime and response monitoring from Better Stack can assert on response content, so a partner feed that starts returning an error envelope with a 200 status pages you instead of silently corrupting a nightly import. These are affiliate links — they cost you nothing and help keep these tools free.

Frequently Asked Questions

Is my XML uploaded anywhere?
No. Parsing and conversion run entirely in your browser using the built-in DOMParser. Nothing is transmitted, stored, or logged, so it is safe to paste SOAP envelopes containing credentials.
Why are my numbers quoted in the JSON?
Because XML has no types — every value in the document is text, and type information lives in a separate XSD schema the converter never sees. Guessing would corrupt identifiers with leading zeros, so nothing is coerced.
What does the @ prefix on some keys mean?
That key was an XML attribute rather than a child element. The prefix prevents an attribute and an element with the same name from colliding, and it lets the JSON convert back to equivalent XML.
Why did a repeated element become an array in one document but not another?
Because arrays are inferred from the document, and a single occurrence is indistinguishable from a non-repeating element without a schema. Normalise with [].concat(value) on read — this is the classic XML-to-JSON pitfall.
Does it handle CDATA sections?
Yes. CDATA content is merged into the element's text exactly as written, so escaped HTML or embedded markup inside a feed item comes through intact.
Can it convert a document with no single root?
No — an XML document must have exactly one root element, and a fragment with several siblings at the top is not well-formed. Wrap it in a container element first.