Convierta XML a JSON (y viceversa) usando Javascript
¿Cómo convertirías de XML a JSON y luego volverías a XML?
Las siguientes herramientas funcionan bastante bien, pero no son completamente consistentes:
- xml2json
¿Alguien se ha encontrado con esta situación antes?
Creo que este es el mejor: Convertir entre XML y JSON
Asegúrese de leer el artículo adjunto en el sitio xml.com de O'Reilly , que detalla los problemas con estas conversiones, lo cual creo que le resultará esclarecedor. El hecho de que O'Reilly sea el anfitrión del artículo debería indicar que la solución de Stefan tiene mérito.
https://github.com/abdmob/x2js : mi propia biblioteca (URL actualizada desde http://code.google.com/p/x2js/ ):
Esta biblioteca proporciona funciones de conversión de XML a JSON (objetos JavaScript) y viceversa. La biblioteca es muy pequeña y no requiere otras bibliotecas adicionales.
Funciones API
- new X2JS(): para crear su instancia y acceder a todas las funciones de la biblioteca. También puede especificar opciones de configuración opcionales aquí
- X2JS.xml2json: convierte XML especificado como objeto DOM a JSON
- X2JS.json2xml - Convertir JSON a objeto DOM XML
- X2JS.xml_str2json: convierte XML especificado como cadena a JSON
- X2JS.json2xml_str - Convertir JSON a cadena XML
Demostración en línea en http://jsfiddle.net/abdmob/gkxucxrj/1/
var x2js = new X2JS();
function convertXml2JSon() {
$("#jsonArea").val(JSON.stringify(x2js.xml_str2json($("#xmlArea").val())));
}
function convertJSon2XML() {
$("#xmlArea").val(x2js.json2xml_str($.parseJSON($("#jsonArea").val())));
}
convertXml2JSon();
convertJSon2XML();
$("#convertToJsonBtn").click(convertXml2JSon);
$("#convertToXmlBtn").click(convertJSon2XML);
Estas respuestas me ayudaron mucho a hacer esta función:
function xml2json(xml) {
try {
var obj = {};
if (xml.children.length > 0) {
for (var i = 0; i < xml.children.length; i++) {
var item = xml.children.item(i);
var nodeName = item.nodeName;
if (typeof (obj[nodeName]) == "undefined") {
obj[nodeName] = xml2json(item);
} else {
if (typeof (obj[nodeName].push) == "undefined") {
var old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(xml2json(item));
}
}
} else {
obj = xml.textContent;
}
return obj;
} catch (e) {
console.log(e.message);
}
}
Siempre que pases un objeto jquery dom/xml: para mí fue:
Jquery(this).find('content').eq(0)[0]
donde contenido era el campo en el que estaba almacenando mi xml.
Creé una función recursiva basada en expresiones regulares, en caso de que no desees instalar la biblioteca y comprender la lógica detrás de lo que está sucediendo:
const xmlSample = '<tag>tag content</tag><tag2>another content</tag2><tag3><insideTag>inside content</insideTag><emptyTag /></tag3>';
console.log(parseXmlToJson(xmlSample));
function parseXmlToJson(xml) {
const json = {};
for (const res of xml.matchAll(/(?:<(\w*)(?:\s[^>]*)*>)((?:(?!<\1).)*)(?:<\/\1>)|<(\w*)(?:\s*)*\/>/gm)) {
const key = res[1] || res[3];
const value = res[2] && parseXmlToJson(res[2]);
json[key] = ((value && Object.keys(value).length) ? value : res[2]) || null;
}
return json;
}
Explicación de expresiones regulares para cada bucle:
- res[0] - devuelve el xml (tal cual)
- res[1] - devuelve el nombre de la etiqueta xml
- res[2] - devuelve el contenido xml
- res[3] - devuelve el nombre de la etiqueta xml en caso de que la etiqueta se cierre sola. Por ejemplo:
<tag />
Puedes comprobar cómo funciona la expresión regular aquí: https://regex101.com/r/ZJpCAL/1
Nota: En caso de que json tenga una clave con un valor indefinido, se eliminará. Por eso inserté null al final de la línea 9.
Estaba usando xmlToJson solo para obtener un valor único del xml.
Descubrí que hacer lo siguiente es mucho más fácil (si el xml solo aparece una vez...)
let xml =
'<person>' +
' <id>762384324</id>' +
' <firstname>Hank</firstname> ' +
' <lastname>Stone</lastname>' +
'</person>';
let getXmlValue = function(str, key) {
return str.substring(
str.lastIndexOf('<' + key + '>') + ('<' + key + '>').length,
str.lastIndexOf('</' + key + '>')
);
}
alert(getXmlValue(xml, 'firstname')); // gives back Hank