Pass file by parameter in a function

Asked

Viewed 78 times

0

I’m doing a function that turns a . xml file into a json file... I found some functions on the internet already, that do this but I do not know how I can pass the file by parameter, as the function asks. I’ll leave the code below for you to know.

function xmlToJson(xml) {

    // Create the return object
    var obj = {};

    if (xml.nodeType == 1) { // element
        // do attributes
        if (xml.attributes.length > 0) {
            obj["@attributes"] = {};
            for (var j = 0; j < xml.attributes.length; j++) {
                var attribute = xml.attributes.item(j);
                obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
            }
        }
    } else if (xml.nodeType == 3) { // text
        obj = xml.nodeValue;
    }

    // do children
    // If just one text node inside
    if (xml.hasChildNodes() && xml.childNodes.length === 1 && xml.childNodes[0].nodeType === 3) {
        obj = xml.childNodes[0].nodeValue;
    }
    else if (xml.hasChildNodes()) {
        for (var i = 0; i < xml.childNodes.length; i++) {
            var item = xml.childNodes.item(i);
            var nodeName = item.nodeName;
            if (typeof (obj[nodeName]) == "undefined") {
                obj[nodeName] = xmlToJson(item);
            } else {
                if (typeof (obj[nodeName].push) == "undefined") {
                    var old = obj[nodeName];
                    obj[nodeName] = [];
                    obj[nodeName].push(old);
                }
                obj[nodeName].push(xmlToJson(item));
            }
        }
    }
    return obj;
}

And in html I’m using an onclick for now:

<a onclick="xmlToJson()" class="menu">
    <div class="card menu-card">
        <div class="card-body">
            <center><h4 id="resultado"></h4></center>
        </div>
    </div>
</a>

1 answer

0


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" />

Browser other questions tagged

You are not signed in. Login or sign up in order to post.