XML to JSON converter
Has anyone written an XML to JSON converter Max object either in C, Java or JavaScript and is willing to share?
Thanks,
Georg
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;
}
... 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 ....
Thanks, there are a number of scripts out there. The questions is whether someone has actually succeeded in getting them to run inside Max.
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,"
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");
}
}
}
}
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
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");
}
}
}
}