Let’s see...
This JSON conversion function works but has some problems. So, I will consider the version of Stefan Goessner, call for xml2json
, with a modification that can be seen on this Github (note: github link coming soon).
Solving the problem
To pass a file as argument to a function, you need to read it somehow. There are some ways of doing: AJAX (with the XMLHttpRequest
) or by means of Uploading user computer file. I will address the second case only because AJAX is extensively documented.
1 - To read a file, we need the corresponding HTML for file selection on the user’s computer:
<input type="file" id="arquivo" />
2 - We also need a open XML file handling function. This function will read the file and only convert to JSON when the file is fully loaded:
function ler_arquivo( e ) {
var arquivo = e.target.files[0]; if ( !arquivo ) return;
var reader = new FileReader();
reader.onload = function( e ) {
// 'conteudo' é uma string (texto puro)
var conteudo = e.target.result;
// transformamos a string em XML
var xmlDOM = new DOMParser()
.parseFromString( conteudo, 'text/xml' );
// transforma o XML em JSON
var meuJSON = xml2json( xmlDOM );
// mostramos no console a versão JSON
console.log( meuJSON ); // trocar pela sua função
};
reader.readAsText( arquivo );
}
3 - We need to add a listening event to know if the user has made the choice of some file. Let’s then also consider the possibility of the user changing the file:
document.getElementById('arquivo')
.addEventListener('change', ler_arquivo, false);
4 - To XML Goessner function for modified JSON can be found in the provided functional example (located below). I’m avoiding putting it on twice 'cause it’s really big and it’s gonna get in the way of reading.
5 - A XML example for testing. Save to your computer and open in the functional example below.
<?xml version="1.0" encoding="UTF-8"?>
<notas>
<nota>
<de>Burro</de>
<para>Google</para>
<assunto>Papai?</assunto>
<mensagem>Não precisa de teste de DNA!</mensagem>
</nota>
<nota>
<de>StackOverflow</de>
<para>Brasil</para>
<assunto>Versão PT</assunto>
<mensagem>Já temos o SOpt!</mensagem>
</nota>
</notas>
Functional example
Below is a functional example that shows the converted XML in JSON. In this case, the result is shown in the console.
function xml2json(xml, tab) {
var X = {
toObj: function(xml) {
var o = {};
if (xml.nodeType==1) { // element node ..
if (xml.attributes.length) // element with attributes ..
for (var i=0; i<xml.attributes.length; i++)
o["@"+xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue||"").toString();
if (xml.firstChild) { // element has child nodes ..
var textChild=0, cdataChild=0, hasElementChild=false;
for (var n=xml.firstChild; n; n=n.nextSibling) {
if (n.nodeType==1) hasElementChild = true;
else if (n.nodeType==3 && n.nodeValue.match(/[^ \f\n\r\t\v]/)) textChild++; // non-whitespace text
else if (n.nodeType==4) cdataChild++; // cdata section node
}
if (hasElementChild) {
if (textChild < 2 && cdataChild < 2) { // structured element with evtl. a single text or/and cdata node ..
X.removeWhite(xml);
for (var n=xml.firstChild; n; n=n.nextSibling) {
if (n.nodeType == 3) // text node
o["#text"] = X.escape(n.nodeValue);
else if (n.nodeType == 4) // cdata node
o["#cdata"] = X.escape(n.nodeValue);
else if (o[n.nodeName]) { // multiple occurence of element ..
if (o[n.nodeName] instanceof Array)
o[n.nodeName][o[n.nodeName].length] = X.toObj(n);
else
o[n.nodeName] = [o[n.nodeName], X.toObj(n)];
}
else // first occurence of element..
o[n.nodeName] = X.toObj(n);
}
}
else { // mixed content
if (!xml.attributes.length)
o = X.escape(X.innerXml(xml));
else
o["#text"] = X.escape(X.innerXml(xml));
}
}
else if (textChild) { // pure text
if (!xml.attributes.length)
o = X.escape(X.innerXml(xml));
else
o["#text"] = X.escape(X.innerXml(xml));
}
else if (cdataChild) { // cdata
if (cdataChild > 1)
o = X.escape(X.innerXml(xml));
else
for (var n=xml.firstChild; n; n=n.nextSibling)
o["#cdata"] = X.escape(n.nodeValue);
}
}
if (!xml.attributes.length && !xml.firstChild) o = null;
}
else if (xml.nodeType==9) { // document.node
o = X.toObj(xml.documentElement);
}
else
alert("unhandled node type: " + xml.nodeType);
return o;
},
toJson: function(o, name, ind) {
var json = name ? ("\""+name+"\"") : "";
if (o instanceof Array) {
for (var i=0,n=o.length; i<n; i++)
o[i] = X.toJson(o[i], "", ind+"\t");
json += (name?":[":"[") + (o.length > 1 ? ("\n"+ind+"\t"+o.join(",\n"+ind+"\t")+"\n"+ind) : o.join("")) + "]";
}
else if (o == null)
json += (name&&":") + "null";
else if (typeof(o) == "object") {
var arr = [];
for (var m in o)
arr[arr.length] = X.toJson(o[m], m, ind+"\t");
json += (name?":{":"{") + (arr.length > 1 ? ("\n"+ind+"\t"+arr.join(",\n"+ind+"\t")+"\n"+ind) : arr.join("")) + "}";
}
else if (typeof(o) == "string")
json += (name&&":") + "\"" + o.toString() + "\"";
else
json += (name&&":") + o.toString();
return json;
},
innerXml: function(node) {
var s = ""
if ("innerHTML" in node)
s = node.innerHTML;
else {
var asXml = function(n) {
var s = "";
if (n.nodeType == 1) {
s += "<" + n.nodeName;
for (var i=0; i<n.attributes.length;i++)
s += " " + n.attributes[i].nodeName + "=\"" + (n.attributes[i].nodeValue||"").toString() + "\"";
if (n.firstChild) {
s += ">";
for (var c=n.firstChild; c; c=c.nextSibling)
s += asXml(c);
s += "</"+n.nodeName+">";
}
else
s += "/>";
}
else if (n.nodeType == 3)
s += n.nodeValue;
else if (n.nodeType == 4)
s += "<![CDATA[" + n.nodeValue + "]]>";
return s;
};
for (var c=node.firstChild; c; c=c.nextSibling)
s += asXml(c);
}
return s;
},
escape: function(txt) {
return txt.replace(/[\\]/g, "\\\\")
.replace(/[\"]/g, '\\"')
.replace(/[\n]/g, '\\n')
.replace(/[\r]/g, '\\r');
},
removeWhite: function(e) {
e.normalize();
for (var n = e.firstChild; n; ) {
if (n.nodeType == 3) { // text node
if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { // pure whitespace text node
var nxt = n.nextSibling;
e.removeChild(n);
n = nxt;
}
else
n = n.nextSibling;
}
else if (n.nodeType == 1) { // element node
X.removeWhite(n);
n = n.nextSibling;
}
else // any other node
n = n.nextSibling;
}
return e;
}
};
if (xml.nodeType == 9) // document node
xml = xml.documentElement;
var json = X.toJson(X.toObj(X.removeWhite(xml)), xml.nodeName, "\t");
return "{\n" + (tab ? json.replace(/\t/g, tab) : json.replace(/\t|\n/g, "")) + "\n}";
}
function ler_arquivo( e ) {
var arquivo = e.target.files[0]; if ( !arquivo ) return;
var reader = new FileReader();
reader.onload = function( e ) {
var conteudo = e.target.result;
var xmlDOM = new DOMParser().parseFromString( conteudo, 'text/xml' );
console.log( xml2json( xmlDOM ) );
};
reader.readAsText( arquivo );
}
document.getElementById('arquivo').addEventListener('change', ler_arquivo, false);
<input type="file" id="arquivo" />