← Todos os artigos

Conversão XML para JSON: atributos, nós de texto, arrays e namespaces

Converta XML para JSON do jeito certo: como atributos, nós de texto, elementos repetidos e namespaces mapeiam para JSON — com convenções, casos extremos e código JS/Python.

Converter XML em JSON soa mecânico até você esbarrar nas partes do XML para as quais JSON não tem equivalente direto: atributos, conteúdo misto de texto e elementos, elementos que aparecem uma ou várias vezes e namespaces. Não existe um único mapeamento „correto“ —— só convenções. Este guia explica as convenções padrão, as decisões que você precisa tomar e como converter XML em JSON em JavaScript, Python e no navegador.

O mapeamento de relance

A maioria dos conversores XML para JSON (xmltodict, fast-xml-parser e a ferramenta deste site) segue a mesma forma: cada elemento vira um objeto, atributos viram chaves com prefixo especial e texto vira o valor ou uma chave reservada.

<!-- XML -->
<note id="1" priority="high">
  <to>Ada</to>
  <from>Bob</from>
  <body>Hello &amp; welcome</body>
</note>
// JSON
{
  "note": {
    "@id": "1",
    "@priority": "high",
    "to": "Ada",
    "from": "Bob",
    "body": "Hello & welcome"
  }
}

Atributos → chaves com prefixo @

Objetos JSON não têm noção de atributo, então a convenção quase universal é prefixar nomes de atributo com @. Isso os distingue dos elementos filhos e torna o mapeamento reversível.

<book id="b1" lang="en"/>
→ { "book": { "@id": "b1", "@lang": "en" } }

Algumas ferramentas usam outro prefixo ($, _) ou um objeto aninhado "@attributes". Escolha um e aplique de forma consistente —— o código que consome precisa saber onde estão os atributos.

Nós de texto e conteúdo misto

Quando um elemento contém apenas texto, ele é reduzido a um valor de string. Mas quando um elemento tem atributos e texto, o texto precisa de um lugar —— por convenção, a chave #text.

<price currency="USD">9.99</price>
→ { "price": { "@currency": "USD", "#text": "9.99" } }

<title>Effective TypeScript</title>
→ { "title": "Effective TypeScript" }

Conteúdo verdadeiramente misto (texto intercalado com elementos filhos, como em marcação tipo HTML) é o caso mais difícil —— a maioria dos conversores orientados a dados concatena ou descarta o texto solto. Se seu XML é de estilo documento em vez de dados, espere perda aqui.

O problema de um vs array

Esta é a armadilha que quebra mais código que qualquer outra. Um elemento que aparece uma vez vira um objeto; o mesmo elemento aparecendo duas vezes vira um array. A forma JSON depende dos dados, não do schema:

<tags><tag>a</tag></tags>
→ { "tags": { "tag": "a" } }          // objeto

<tags><tag>a</tag><tag>b</tag></tags>
→ { "tags": { "tag": ["a", "b"] } }   // array

Consumidores que esperam tags.tag como array sempre vão quebrar com um único elemento. Duas soluções: configure o parser para tratar elementos repetíveis conhecidos sempre como arrays, ou normalize após o parse (const arr = [].concat(node.tag ?? [])).

Namespaces

Namespaces XML usam prefixos (soap:Envelope) ligados por declarações xmlns. JSON não tem conceito de namespace, então conversores tendem a uma destas estratégias:

  • Manter o prefixo na chave —— "soap:Envelope". Simples e reversível, mas a chave contém dois-pontos e você precisará de acesso por colchetes (obj["soap:Envelope"]).
  • Remover o prefixo —— "Envelope". Chaves mais limpas, mas você perde o namespace e arrisca colisões entre dois namespaces que compartilham o mesmo nome local.
  • Manter xmlns como atributos —— declarações viram chaves "@xmlns:soap" para que o vínculo sobreviva ao round-trip.

Para a maioria das tarefas de dados, manter o prefixo na chave é o padrão mais seguro —— nunca perde informação.

Entidades e CDATA

Um conversor correto decodifica as cinco entidades predefinidas (&lt;, &gt;, &amp;, &quot;, &apos;) e as referências numéricas (&#169;) para seus caracteres, e trata blocos <![CDATA[...]]> como texto literal.

Convenções nomeadas: BadgerFish, GData, Parker

A atribuição „@ para atributos / #text para texto“ não é a única em circulação. Três convenções nomeadas que você verá ao ler saídas XML→JSON de outros sistemas:

  • BadgerFish —— atributos sob chave prefixada com @; texto sob $; declarações de namespace sob @xmlns. Verboso, mas sem perdas.
  • GData —— variante do Google: atributos prefixados com $; texto sob $t; elementos repetidos sempre são arrays. Sem perdas e com forma previsível.
  • Parker —— descarta atributos por completo; o mapeamento mais simples e com mais perdas. Útil quando você controla os dois lados e só interessam os valores dos elementos.

Quando integrar com um sistema que já produz JSON-de-XML, identifique antes qual convenção ele usa, antes de escrever código de parsing.

Consultar o resultado com JSONPath

Depois de converter o XML, você pode referenciar valores com JSONPath. Dois pequenos ajustes em relação aos hábitos de XPath:

  • As chaves de atributo levam o prefixo @ do mapeamento, então o @id do XPath vira $..['@id'] em JSONPath.
  • A questão um-vs-array faz com que um XPath que funciona como book/title possa precisar ser $..book[*].title em JSONPath para lidar com as duas formas.

Como converter XML em JSON no código

// JavaScript (navegador) —— DOMParser + uma pequena travessia, ou uma biblioteca:
import { XMLParser } from 'fast-xml-parser';
const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@' });
const obj = parser.parse(xmlString);

# Python —— xmltodict mapeia atributos para "@name" e texto para "#text"
import xmltodict, json
doc = xmltodict.parse(xml_string)
print(json.dumps(doc, indent=2))

Converter XML em JSON online

Para uma conversão rápida, cole seu XML no conversor JSON ⇄ XML e clique em To JSON. Ele aplica as convenções acima —— @ para atributos, #text para conteúdo misto, arrays para elementos repetidos —— e roda totalmente no navegador, então feeds internos e payloads de API nunca saem da sua máquina.

Perguntas frequentes

Como atributos XML são representados em JSON?

Por convenção, viram chaves prefixadas com @ (ex.: @id), distintas dos elementos filhos, para que o mapeamento possa ser revertido.

Por que o mesmo elemento às vezes vira objeto e às vezes array?

Porque a forma segue os dados: uma ocorrência vira objeto, várias viram array. Configure o parser para tratar elementos repetíveis conhecidos como arrays, ou normalize com [].concat(value) após o parse.

O que acontece com o texto dentro de um elemento com atributos?

Ele fica sob a chave reservada #text, já que o objeto já contém os atributos. Um elemento com apenas texto se reduz a uma string simples.

Como namespaces XML são tratados?

JSON não tem namespaces. A abordagem mais segura mantém o prefixo na chave ("soap:Envelope") e as declarações xmlns como atributos @xmlns:* para não perder nada.

Ferramentas e guias relacionados