XML to JSON Converter

Attributes, repeated tags and text content, mapped to plain JSON keys.

From
To
XML input290 characters
JSON result
{
  "products": {
    "product": [
      {
        "@sku": "SKU-100",
        "name": "Wireless Mouse",
        "price": {
          "@currency": "BRL",
          "#text": "129.90"
        }
      },
      {
        "@sku": "SKU-204",
        "name": "Mechanical Keyboard",
        "price": {
          "@currency": "BRL",
          "#text": "349.00"
        }
      }
    ]
  }
}
Written and maintained by Pura IALast reviewed

The hard part of turning XML into JSON isn't syntax, it's that XML carries information JSON has no native place for: attributes, and text that sits next to child elements rather than being the only content. This converter's rule for both is explicit rather than implied — see the mapping below — and it's the same rule /json/to-xml uses in reverse, so a round trip through both pages is stable for the shapes this covers.

The example below — a small product feed, the kind an older internal API might return — is loaded into the converter above. Each <product> carries a sku attribute and a nested <price> that itself has a currency attribute and text: exactly the case that needs both @ and #text to represent faithfully.

Before and after

This is loaded in the converter above.

XML
<?xml version="1.0" encoding="UTF-8"?>
<products>
  <product sku="SKU-100">
    <name>Wireless Mouse</name>
    <price currency="BRL">129.90</price>
  </product>
  <product sku="SKU-204">
    <name>Mechanical Keyboard</name>
    <price currency="BRL">349.00</price>
  </product>
</products>
JSON
{
  "products": {
    "product": [
      {
        "@sku": "SKU-100",
        "name": "Wireless Mouse",
        "price": {
          "@currency": "BRL",
          "#text": "129.90"
        }
      },
      {
        "@sku": "SKU-204",
        "name": "Mechanical Keyboard",
        "price": {
          "@currency": "BRL",
          "#text": "349.00"
        }
      }
    ]
  }
}

How the mapping works

Attributes become @-prefixed keys

sku="SKU-100" on a <product> element becomes "@sku": "SKU-100" in its JSON object. The @ keeps attributes visually distinct from child elements when you're reading the JSON, and is what /json/to-xml looks for to convert back the other way.

An element with only text collapses to a plain string

<name>Wireless Mouse</name> becomes "name": "Wireless Mouse" directly — not {"#text": "Wireless Mouse"} — because there is nothing else on that element (no attributes, no children) that the #text key would need to sit alongside.

<price currency="BRL">129.90</price>

...but #text appears once there's also an attribute

The <price> element above has both an attribute and text, so it cannot collapse to a bare string — there would be nowhere to put the currency. It becomes {"@currency": "BRL", "#text": "129.90"} instead.

Repeated tags become one array, in document order

Two <product> elements under <products> become one "product" array with two entries, in the order they appeared — not two separate keys and not merged into one object. A single <product> (no siblings) stays a plain object, not a one-item array.

Every value becomes a string — on purpose

XML text is always just characters; XML itself has no number or boolean type. 129.90 above stays the string "129.90" rather than being parsed into the number 129.9, which would also silently normalize away that trailing zero. Guessing the type would be exactly that — a guess — the same call this site's JSON-to-TypeScript converter makes for the same reason.

Known limitations

  • Mixed content — text interleaved with child elements, like <p>Hello <b>world</b>!</p> — loses the ordering between the text and the element: it becomes {"#text": "Hello !", "b": "world"}, which can't distinguish that from "!<b>world</b>Hello ". This converter is built for structured, config- and API-shaped XML, not prose-like markup, and this is where that shows.
  • XML namespaces are treated as plain string prefixes — soap:Envelope becomes the JSON key "soap:Envelope" as literal text, not resolved against its xmlns declaration. This is a real, deliberate scope limit: namespace-aware resolution is a meaningfully larger problem than the config-and-API-response XML this converter targets.
  • Comments and processing instructions are dropped — they aren't data, so there's no JSON key for them to become.

XML to JSON FAQ

Why does one element become a plain string and another become an object?

An element with no attributes and no children collapses to just its text, as a string. One with an attribute, a child element, or both becomes an object — because a plain string has nowhere to attach that extra information.

What happens to XML comments?

They're dropped. Comments document the XML for a human reader; they aren't part of the data, so there's no corresponding JSON value for them.

Does it handle CDATA sections?

Yes — the content inside <![CDATA[ ... ]]> is taken verbatim as text, without re-parsing it as markup, exactly like a normal text node.

Is my XML uploaded anywhere?

No. Parsing and conversion both run in your browser using this site's own XML parser, not a server call.

Other conversions

Every direction between JSON, XML and YAML — including YAML as a starting point — is available directly from the From/To selectors in the converter above, whichever page you're on.