XML to JSON converter

Georg Hajdu's icon

Has anyone written an XML to JSON converter Max object either in C, Java or JavaScript and is willing to share?

Thanks,

Georg

Jan M's icon

I have some JavaScript something that was written for Browsers. It's not tested on Max (And in fact I don't even know in as far the XML-Dom model in implemented in Max/JavaScript). But Maybe it can serve as a starting point.

Attributes are appended as NamedNodeMaps as '@' and if an element has more than one child with the same TagName tey are parsed into an array (otherwise they stay objects...)

/**
         * Parse an XmlNode recursivly into JSON
         * TODO Test behavior if a node has siblings of the same NodeType and child-nodes
         */
        var toJSON = function(xmlNode, jsonObject) {
            if(!xmlNode) return;
            jsonObject = jsonObject || {};
            if($(xmlNode).children().length >= 1 ){
                jsonObject[xmlNode.nodeName] = { '@' : xmlNode.attributes};
                $.each($(xmlNode).children(),function(index, childElement){
                    toJSON(childElement, jsonObject[xmlNode.nodeName]);
                });
            } else {
                if(jsonObject[xmlNode.nodeName] == undefined) {
                    jsonObject[xmlNode.nodeName] = {value : $(xmlNode).text(), '@' : xmlNode.attributes};
                } else {
                    if($.isArray(jsonObject[xmlNode.nodeName])) {
                        var nodeText = $(xmlNode).text();
                        var nodeName = xmlNode.nodeName;
                        jsonObject[xmlNode.nodeName].push({value : nodeText, '@' : xmlNode.attributes});
                    } else {
                        // Get existing Values
                        var existingAttributes = jsonObject[xmlNode.nodeName]['@']
                        var exitsingValue = jsonObject[xmlNode.nodeName]['value']
                        var nodeText = $(xmlNode).text();
                        jsonObject[xmlNode.nodeName] = [];
                        jsonObject[xmlNode.nodeName].push({value : exitsingValue, '@' : existingAttributes});
                        jsonObject[xmlNode.nodeName].push({value : nodeText, '@' : xmlNode.attributes});
                    }
                }
            }
            return jsonObject;
        }
Jan M's icon

... just see that there is also some jQuery inside ($.isArray()) -> this won't work for sure... so it's probably really more an inspiration, than a solution ....

Georg Hajdu's icon

Thanks, there are a number of scripts out there. The questions is whether someone has actually succeeded in getting them to run inside Max.

Georg Hajdu's icon

I found this script, but I don't know how to convert the jsonobject to text (my naive attempt to use the toString() method) failed miserably, and I also don't know what to do with the last two ifs—they're probably browser-related:

/*
xml2json v 1.1
copyright 2005-2007 Thomas Frank

This program is free software under the terms of the
GNU General Public License version 2 as published by the Free
Software Foundation. It is distributed without any warranty.
*/
autowatch = 1;

inlets = 1;
outlets = 1;

function input(myXML)
{
myJsonObject=xml2json.parser(myXML);
outlet(0,myJsonObject.toString());
post(myJsonObject);
post();
}

xml2json={
    parser:function(xmlcode,ignoretags,debug){
        if(!ignoretags){ignoretags=""};
        xmlcode=xmlcode.replace(/s*/>/g,'/>');
        xmlcode=xmlcode.replace(/]*>/g,"").replace(/]*>/g,"");
        if (!ignoretags.sort){ignoretags=ignoretags.split(",")};
        var x=this.no_fast_endings(xmlcode);
        x=this.attris_to_tags(x);
        x=escape(x);
        x=x.split("%3C").join("").split("%3D").join("=").split("%22").join(""");
        for (var i=0;i
            x=x.replace(new RegExp("","g"),"*$**"+ignoretags[i]+"**$*");
            x=x.replace(new RegExp("","g"),"*$***"+ignoretags[i]+"**$*")
        };
        x=''+x+'';
        this.xmlobject={};
        var y=this.xml_to_object(x).jsontagwrapper;
        if(debug){y=this.show_json_structure(y,debug)};
        return y
    },
    xml_to_object:function(xmlcode){
        var x=xmlcode.replace(/
        x=x.split("
        var y=[];
        var level=0;
        var opentags=[];
        for (var i=1;i
            var tagname=x[i].split(">")[0];
            opentags.push(tagname);
            level++
            y.push(level+"
            while(x[i].indexOf("§"+opentags[opentags.length-1]+">")>=0){level--;opentags.pop()}
        };
        var oldniva=-1;
        var objname="this.xmlobject";
        for (var i=0;i
            var preeval="";
            var niva=y[i].split("
            var tagnamn=y[i].split("")[0];
            tagnamn=tagnamn.toLowerCase();
            var rest=y[i].split(">")[1];
            if(niva
                var tabort=oldniva-niva+1;
                for (var j=0;j
            };
            objname+="."+tagnamn;
            var pobject=objname.substring(0,objname.lastIndexOf("."));
            if (eval("typeof "+pobject) != "object"){preeval+=pobject+"={value:"+pobject+"};n"};
            var objlast=objname.substring(objname.lastIndexOf(".")+1);
            var already=false;
            for (k in eval(pobject)){if(k==objlast){already=true}};
            var onlywhites=true;
            for(var s=0;s
                if(rest.charAt(s)!="%"){onlywhites=false}
            };
            if (rest!="" && !onlywhites){
                if(rest/1!=rest){
                    rest="'"+rest.replace(/'/g,"\'")+"'";
                    rest=rest.replace(/*$***/g,"
                    rest=rest.replace(/*$**/g,"
                    rest=rest.replace(/**$*/g,">")
                }
            }
            else {rest="{}"};
            if(rest.charAt(0)=="'"){rest='unescape('+rest+')'};
            if (already && !eval(objname+".sort")){preeval+=objname+"=["+objname+"];n"};
            var before="=";after="";
            if (already){before=".push(";after=")"};
            var toeval=preeval+objname+before+rest+after;
            eval(toeval);
            if(eval(objname+".sort")){objname+="["+eval(objname+".length-1")+"]"};
            oldniva=niva
        };
        return this.xmlobject
    },
    show_json_structure:function(obj,debug,l){
        var x='';
        if (obj.sort){x+="[n"} else {x+="{n"};
        for (var i in obj){
            if (!obj.sort){x+=i+":"};
            if (typeof obj[i] == "object"){
                x+=this.show_json_structure(obj[i],false,1)
            }
            else {
                if(typeof obj[i]=="function"){
                    var v=obj[i]+"";
                    //v=v.replace(/t/g,"");
                    x+=v
                }
                else if(typeof obj[i]!="string"){x+=obj[i]+",n"}
                else {x+="'"+obj[i].replace(/'/g,"\'").replace(/n/g,"\n").replace(/t/g,"\t").replace(/r/g,"\r")+"',n"}
            }
        };
        if (obj.sort){x+="],n"} else {x+="},n"};
        if (!l){
            x=x.substring(0,x.lastIndexOf(","));
            x=x.replace(new RegExp(",n}","g"),"n}");
            x=x.replace(new RegExp(",n]","g"),"n]");
            var y=x.split("n");x="";
            var lvl=0;
            for (var i=0;i
                if(y[i].indexOf("}")>=0 || y[i].indexOf("]")>=0){lvl--};
                tabs="";for(var j=0;j
                x+=tabs+y[i]+"n";
                if(y[i].indexOf("{")>=0 || y[i].indexOf("[")>=0){lvl++}
            };
            if(debug=="html"){
                x=x.replace(//g,">");
                x=x.replace(/n/g,"").replace(/t/g,"

$Adam's icon

Hi Georg,

There's an XSL transformation which converts XMLs to JSON files, available on this site:

Then, with mxj quickie, one can create a very simple class which makes XSL transformations:

 import com.cycling74.max.*;
 import java.io.File;
 import java.io.ByteArrayOutputStream;
 import java.io.StringReader;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.stream.StreamSource;
 import javax.xml.transform.stream.StreamResult;

 public class xslt extends MaxObject
 {
     private Transformer transformer;
     public xslt(Atom[] args) {
         declareInlets(new int[]{DataTypes.ALL, DataTypes.ALL});
         declareOutlets(new int[]{DataTypes.ALL});
         setInletAssist(new String[]{"XML inlet", "XSLT inlet"});
         setOutletAssist(new String[]{"XML result"});
     }
     public void anything(String msg, Atom[] args) {
         String source = msg;
         for ( Atom a : args ) {
             source += " " + a.toString ( );
         }
         if (getInlet()==0){
             // Convert XML
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
             try {
                 transformer.transform(new StreamSource(new StringReader(source)), new StreamResult(outputStream));
             } catch (Exception e) {
                 // This is BAD CODING, exceptions must always be managed better than here...
                 bail("FLÖFF");
             }
             outlet(0,outputStream.toString());
         } else {
             // Import XSLT
             try {
                 transformer = TransformerFactory.newInstance().newTemplates(new StreamSource(new File(msg))).newTransformer();
             } catch (Exception e) {
                 // Oh, no! Not again...
                 bail("BOING");
             }
         }
     }
 }
Max Patch
Copy patch and select New From Clipboard in Max.

If you compile this class with mxj quickie, you'll be able to transform any XML into any other format that can be transformed automatically by XSLT-s. For instance, you could translate score-partwise MusicXML files to score-timewise ones using the XSLT provided by the developers of MusicXML, or by using the XSLT of the mentioned website, you would also be able to transform an XML to a JSON file. See this very simple patch for an example:

Hope this helps,
Ádám

$Adam's icon

Hm... Interesting... I used the 'pre' tags, but the code is just flushed... :-( I try it again:


import com.cycling74.max.*;
import java.io.File;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;

public class xslt extends MaxObject
{
    private Transformer transformer;
    public xslt(Atom[] args) {
        declareInlets(new int[]{DataTypes.ALL, DataTypes.ALL});
        declareOutlets(new int[]{DataTypes.ALL});
        setInletAssist(new String[]{"XML inlet", "XSLT inlet"});
        setOutletAssist(new String[]{"XML result"});
    }
    public void anything(String msg, Atom[] args) {
        String source = msg;
        for ( Atom a : args ) {
            source += " " + a.toString ( );
        }
        if (getInlet()==0){
            // Convert XML
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            try {
                transformer.transform(new StreamSource(new StringReader(source)), new StreamResult(outputStream));
            } catch (Exception e) {
                // This is BAD CODING, exceptions must always be managed better than here...
                bail("FLÖFF");
            }
            outlet(0,outputStream.toString());
        } else {
            // Import XSLT
            try {
                transformer = TransformerFactory.newInstance().newTemplates(new StreamSource(new File(msg))).newTransformer();
            } catch (Exception e) {
                // Oh, no! Not again...
                bail("BOING");
            }
        }
    }
}