There is now a webapp api of this too which you can use to convert online. See Using Apps Script for xml json conversion
How to use
Let’s start with this JavaScript object that we need to convert to XML for some inexplicable reason. It contains examples of most of the type of things you’d need to create. All the values will be converted to text nodes, without attributes.
var myObject = { "aString": "some string", "aNumber": 8, "aBoolean": false, "anObject": { "apis": [{ "name":"numbers", "url":"http://numbersapi.com/" }], }, "anArray": [ { "value": 8 , "result": "legs an arachnid has" }, { "value": 8 , "result": "furlongs in a mile" } ], "anotherArray":[1,2,3] };
It can be used like this
var root = makeXmlFromOb (myObject , XmlService.createElement('root')); // make a documents var doc = XmlService.createDocument(root); // show it Logger.log (XmlService.getPrettyFormat().format(doc));
The result
This uses the tag element to indicate a member of an array. The second solution on this page takes a different (and better approach).
some string 8 false numbers http://numbersapi.com/ 8 legs an arachnid has 8 furlongs in a mile 1 2 3
The code
It’s recursive, so in the end it’s just a few lines of code.
/** * convert json to xml * @param {object] ob an object to convert * @param {XmlElement} parent usually the root on first call * @return {XmlElement} the parent for chaining */ function makeXmlFromOb (ob, parent) { // this is recursive to deal with multi level JSON objects Object.keys(ob).forEach (function (d) { // if the key is numeric, xml will fail, so rename array indices to value var child = XmlService.createElement(isNaN(new Number(d)) ? d : 'element' ); // add new created element to the parent parent.addContent (child); // need to recurse if this is an object/array if (typeof ob[d] === 'object' ) { // the new parent is the newly created node return makeXmlFromOb (ob[d] , child ); } else { // regular node, set the text to the value child.setText(ob[d]); } }); return parent; }
An alternative approach.
Arrays are funny things in XML, since they are identified by a repetition of a tag, rather than being specifically called out as an array as they are in JSON. In the example above, I’ve inserted a new tag
Consider this object. var myObject = { "aString": "some string", "aNumber": 8, "aBoolean": false, "anObject": { "apis": [{ "name":"numbers", "url":"http://numbersapi.com/" },{ "name":"faa", "url":"http://services.faa.gov/airport/status" }], }, "anArray": [ { "value": 8 , "result": "legs an arachnid has" }, { "value": 8 , "result": "furlongs in a mile" } ], "anotherArray":[1,2,3] };
and the result using the modified approach
some string 8 false numbers http://numbersapi.com/ faa http://services.faa.gov/airport/status 8 legs an arachnid has 8 furlongs in a mile 1 2 3
This makes xml that can be reversed back out to JSON, and makes a better solution in my opinion, except that arrays with just 1 member are not distinguishable as arrays.
/** * convert json to xml * @param {object] ob an object to convert * @param {XmlElement} parent usually the root on first call * @return {XmlElement} the parent for chaining */ function makeXmlFromOb (ob, parent) { // this is recursive to deal with multi level JSON objects Object.keys(ob).forEach (function (d,i) { // if its an array, we repeat the key name of the parent if (Array.isArray(ob)) { if (i === 0 ) { // the first element already exists var child = parent; } else { var child = XmlService.createElement(parent.getName()); parent.getParentElement().addContent(child); } } else { var child = XmlService.createElement(d); parent.addContent (child); } // need to recurse if this is an object/array if (typeof ob[d] === 'object' ) { // the new parent is the newly created node return makeXmlFromOb (ob[d] , child ); } else { // regular node, set the text to the value child.setText(ob[d]); } }); return parent; }