Skip to content

Instantly share code, notes, and snippets.

@Redsandro
Forked from mediaupstream/json2xml.js
Created May 31, 2012 11:11
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Redsandro/2842694 to your computer and use it in GitHub Desktop.
Save Redsandro/2842694 to your computer and use it in GitHub Desktop.
json2xml NodeJS Module - Convert an xml2js JSON object back to XML
/**
* json2xml NodeJS Module - Convert an xml2js JSON object back to XML
*
* Redsandro - changed into requirable
*
* @author Derek Anderson
* @copyright 2011 Media Upstream
* @license MIT License
* @url https://gist.github.com/1495793
*
* Usage:
* json2xml = require('./json2xml').json2xml;
*
* json2xml({"jsonObject": "@": { "attribute": "value", "foo": "bar" }}, "rootElement", function(xml) {
* console.log(xml); // log the XML data
* });
*
* License
* -------
*
* Copyright (c) 2011 Derek Anderson / Media Upstream
* https://gist.github.com/1495793
*
* Copyright (c) 2012 Redsandro - Turned into NodeJS Module
* http://www.redsandro.com/
*
* The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*/
exports.json2xml = function(json, root, cb){
var recursion = 0;
var xml = '<?xml version="1.0" ?>';
var isArray = function(obj) { return obj.constructor == Array; };
var parseAttributes = function(node){
for(key in node){
var value = node[key];
xml += ' ' + key +'="'+ value +'"';
};
xml += '>';
};
var parseNode = function(node, parentNode){
recursion++;
// Handle Object structures in the JSON properly
if(!isArray(node)){
xml += '<'+ parentNode;
if(typeof node == 'object' && node['@']){
parseAttributes(node['@']);
} else {
xml += '>';
}
for(key in node){
var value = node[key];
// text values
if(typeof value == 'string'){
if(key === '#'){
xml += value;
} else {
xml += '<'+ key +'>'+ value + '</'+key+'>';
}
}
// is an object
if(typeof value == 'object' && key != '@'){
parseNode(node[key], key);
}
}
recursion--;
xml += '</'+ parentNode +'>';
}
// Handle array structures in the JSON properly
if(isArray(node)){
for(var i=0; i < node.length; i++){
parseNode(node[i], parentNode);
}
recursion--;
}
if (recursion === 0) { cb(xml); }
};
parseNode(json, root); // fire up the parser!
};
@akamensky
Copy link

The example does not work with node.js.
The JSON object is invalid in that case, with valid JSON there is no way to add attributes to a node.

@Redsandro
Copy link
Author

This does work with node.js and it is proper json.
As you can see, attributes are added in a key called '@'.

@valeriod
Copy link

valeriod commented Aug 6, 2013

There is a curly bracket missing, the proper notation for the JSON object is {"jsonObject": {"@": { "attribute": "value", "foo": "bar" }}}

@ql
Copy link

ql commented Sep 17, 2013

Looks like it doesn't work right with arrays :(

 in {"trk":{"trkseg":[{"trkpt":{"time":9}},{"trkpt":{"time":0}}]}}
 out <?xml version="1.0" ?><gpx><trk><trkseg><trkpt></trkpt></trkseg><trkseg><trkpt></trkpt></trkseg></trk></gpx>

@Redsandro
Copy link
Author

Hey @ql - sorry I hadn't seen this message. I just borrowed someone's code and node-ified it. Worked for my purposes.

Of course a bit further down the journey, we are better off just like to use someone's npm package. There is however some choice, and there's no clear winner.

This one is just not very nicely written imo, and has some non-versatile tricks like removing the s from array keys.

We should probably remove the ones that cannot easily convert an object to xml attributes without renaming all the keys.

Now these modules allow for multiple root elements, which is not allowed in XML, so I don't trust these are mature modules:

So we have three left that make sense. However none of the mentioned modules call back. They are all blocking. I should strike out these too for that, but we'll have nothing left.

What is your opinion? What do you use these days for your JSON to XML needs?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment