5.5 — Transformación de documentos con JavaScript
Los sistemas no hablan el mismo idioma
Llevas varias unidades trabajando con JSON. Ya sabes consumirlo desde una API, guardarlo en localStorage y manipularlo con JavaScript. Pero el mundo real no es solo JSON.
Imagina que una empresa lleva 15 años guardando su catálogo de productos en XML. Ahora quieren una web moderna que muestre ese catálogo de forma dinámica. El problema: tu JavaScript, tu framework, tu librería de gráficos... todo espera JSON. Nadie espera XML.
¿Tiras el catálogo y lo reescribes a mano en JSON? No. Lo transformas automáticamente.
Eso es lo que aprenderás aquí: convertir datos entre formatos distintos usando JavaScript. No porque sea un ejercicio académico, sino porque en el mundo real los sistemas no siempre se ponen de acuerdo en cómo guardan la información.
Los tres formatos que vas a ver toda tu carrera
JSON — el que ya conoces
{
"nombre": "Lucía",
"edad": 19,
"asignaturas": ["LMSGI", "Programación"]
}
JSON es el formato nativo de JavaScript. Es ligero, fácil de leer y prácticamente todas las APIs modernas lo usan. Soporta estructuras anidadas: objetos dentro de objetos, listas de objetos, lo que necesites. Ya lo has usado extensamente en las unidades anteriores.
XML — el que encuentras en sistemas antiguos
<alumno>
<nombre>Lucía</nombre>
<edad>19</edad>
</alumno>
XML fue el estándar dominante durante años y todavía aparece en muchos sistemas empresariales, servicios de la administración pública y APIs heredadas. Es más verboso que JSON — cada dato necesita una etiqueta de apertura y una de cierre — pero también más formal y estructurado. No lo vas a elegir si partes de cero, pero sí lo vas a encontrar y tendrás que saber manejarlo.
CSV — el que todo el mundo entiende
nombre,edad
Lucía,19
Pedro,20
CSV es el formato más simple de los tres: filas de valores separados por comas. No soporta estructuras anidadas ni listas, pero tiene una ventaja enorme: cualquiera puede abrirlo en Excel. Por eso sigue siendo el formato más usado para exportar informes, importar datos masivos y compartir tablas entre sistemas que no tienen nada en común.
¿Cuándo usar cada uno?
| Formato | Úsalo cuando... |
|---|---|
| JSON | Trabajas con APIs, frontend o cualquier sistema moderno |
| XML | Consumes un servicio antiguo o trabajas con sistemas empresariales |
| CSV | Exportas datos tabulares o necesitas compatibilidad con Excel |
Transformando documentos con JavaScript puro
JavaScript tiene herramientas nativas para trabajar con los tres formatos sin instalar nada.
De XML a JSON
El navegador incluye DOMParser, un objeto que convierte texto XML en un árbol de nodos que puedes recorrer igual que el DOM de una página HTML.
const xmlTexto = `
<persona>
<nombre>Lucía</nombre>
<edad>22</edad>
</persona>
`;
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlTexto, "application/xml");
function xmlToJson(xml) {
const obj = {};
for (let node of xml.children) {
obj[node.nodeName] = node.textContent;
}
return obj;
}
console.log(xmlToJson(xmlDoc.documentElement));
// { nombre: "Lucía", edad: "22" }
parseFromString convierte el texto XML en un documento navegable. Luego recorremos sus nodos hijos y guardamos cada nombre de etiqueta como clave y su contenido como valor.
Un detalle importante: DOMParser solo funciona en el navegador, no en Node.js. Si necesitas transformar XML en el servidor, tendrás que usar una librería como xml2js, que veremos más adelante.
Esta función también es simple: solo funciona con XML plano de un nivel. Cuando el XML tiene atributos, nodos anidados o listas, la cosa se complica. Para esos casos existe xml2js.
De CSV a JSON
La primera línea tiene los nombres de columna y cada línea siguiente es un registro:
const csv = `nombre,edad
Lucía,22
Pedro,21`;
function csvToJson(csv) {
const [cabecera, ...filas] = csv.trim().split("\n");
const campos = cabecera.split(",");
return filas.map(fila => {
const valores = fila.split(",");
const obj = {};
campos.forEach((campo, i) => obj[campo] = valores[i]);
return obj;
});
}
console.log(csvToJson(csv));
// [ { nombre: "Lucía", edad: "22" }, { nombre: "Pedro", edad: "21" } ]
Un detalle importante: todos los valores llegan como strings. Si edad tiene que ser un número, tendrás que convertirlo: Number(valores[i]) o parseInt(valores[i]). Esta función también falla si algún campo contiene una coma dentro del valor — para esos casos existe PapaParse.
De JSON a CSV
Extraemos las claves del primer objeto como cabecera y los valores de cada objeto como filas:
const datos = [
{ nombre: "Lucía", edad: 22 },
{ nombre: "Pedro", edad: 21 }
];
function jsonToCsv(datos) {
const cabecera = Object.keys(datos[0]).join(",");
const filas = datos.map(obj => Object.values(obj).join(","));
return [cabecera, ...filas].join("\n");
}
console.log(jsonToCsv(datos));
// nombre,edad
// Lucía,22
// Pedro,21
Librerías cuando el código manual no es suficiente
Las funciones anteriores funcionan para casos simples. En un proyecto real el CSV puede tener campos con comas dentro de comillas, el XML puede tener atributos y nodos profundamente anidados, o simplemente tienes miles de registros. Para eso existen librerías especializadas.
La regla práctica es la misma que siempre: para aprender, escribe el código tú. Para producción, usa la librería.
xml2js — XML serio en Node.js
xml2js convierte XML en JSON automáticamente, manejando atributos, nodos anidados y listas sin que tengas que escribir funciones personalizadas.
npm install xml2js
const fs = require('fs');
const xml2js = require('xml2js');
const xml = fs.readFileSync('catalogo.xml', 'utf8');
xml2js.parseString(xml, (err, result) => {
if (err) {
console.error("Error al parsear el XML:", err);
return;
}
console.log(result);
// XML convertido en objeto JavaScript, listo para usar
});
fs.readFileSync lee el archivo del disco. parseString hace la conversión y te devuelve el resultado en el callback. A partir de ahí tienes un objeto JavaScript normal.
PapaParse — CSV sin dolores de cabeza
Las funciones CSV que escribimos antes fallan en cuanto aparece un campo que contiene comas, saltos de línea o comillas. PapaParse maneja todo eso correctamente y además puede leer archivos reales que el usuario sube desde su ordenador.
<script src="https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.js"></script>
CSV a JSON:
const csvData = `nombre,edad\nLucía,22\nPedro,21`;
Papa.parse(csvData, {
header: true, // La primera fila contiene los nombres de columna
dynamicTyping: true, // Convierte números automáticamente
complete: function(results) {
console.log(results.data);
// [ { nombre: "Lucía", edad: 22 }, { nombre: "Pedro", edad: 21 } ]
}
});
Fíjate en dynamicTyping: true. Con eso PapaParse detecta automáticamente que edad es un número y lo convierte. Eso es exactamente lo que diferencia una librería bien hecha de la función que escribimos antes.
JSON a CSV:
const datos = [
{ nombre: "Lucía", edad: 22 },
{ nombre: "Pedro", edad: 21 }
];
const csv = Papa.unparse(datos);
console.log(csv);
Ejercicio
Tienes este XML con un pequeño catálogo de productos:
<catalogo>
<producto>
<nombre>Teclado mecánico</nombre>
<precio>89.99</precio>
<stock>14</stock>
</producto>
<producto>
<nombre>Monitor 27"</nombre>
<precio>349.00</precio>
<stock>5</stock>
</producto>
</catalogo>
Tu tarea es convertirlo a JSON usando DOMParser y renderizar cada producto como una tarjeta en el HTML, mostrando nombre, precio y stock.
Cuando lo tengas funcionando, prueba a añadir un tercer producto directamente en el XML y comprueba que aparece automáticamente en la página sin tocar el JavaScript.
Como extensión, exporta el catálogo a CSV usando jsonToCsv. ¿Qué pasa si el nombre de un producto contiene una coma? ¿Cómo lo resolverías?