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 XML string that needs to be converted to a JSON object.
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
It can be used like this
var obFromXml = makeObFromXml ( XmlService.parse (xmlString).getRootElement() );Page Content hideThe result
This is able to reverse the conversion done by the second approach used in Convert JSON to XML. Any XML attributes will be converted to regular key/value pairs, since the concept of an attribute doesn't exist in JSON. I did consider creating an attribute object, but in the end decided on this approach where a value and an attribute are considered the same. If an element has both attributes and a text node, the text node will be added to a property called text.{ "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] }The code
It's recursive, so in the end it's just a few lines of code. Note that it converts numbers and booleans from text in the fixValue function. This could easily be extended to convert dates or unescape strings between JSON and XML formats if necessary.
/** * traverse an xml tree and create a js object * @param {XmlElement} xmlElement the parent * @return {object||string} a new branch */ function makeObFromXml(xmlElement) { // parent for this iteration var job = {}; var name = xmlElement.getName(); // attributes are converted to children xmlElement.getAttributes().forEach(function(d) { var child = XmlService.createElement(d.getName()); child.setText(d.getValue()); xmlElement.addContent(child); }); // any children var kids = xmlElement.getChildren(); if (!kids.length) { // its just a value return fixValue(xmlElement.getText()); } else { // if there are any children we need to recurse kids.forEach (function(d) { store ( job , d.getName() , makeObFromXml(d)); }); // if there is also a text node, we need to add that too, but also create a node for it store (job , 'text' , fixValue(xmlElement.getText())); } return job; function store( job , name , value ) { // if it's a repeated key, then we need to turn into an array if (job.hasOwnProperty(name) && !Array.isArray (job[name])) { job[name] = [job[name]]; } // push or assign if (value !== '') { if (Array.isArray (job[name])) { job[name].push (value); } else { job[name] = value; } } } /** * converts strings from xml back to regular types * @param {string} value the string value * @param {*} a native type */ function fixValue (value) { // is it truthy/falsely var lowerValue = value.toLowerCase().trim(); if (lowerValue === false.toString()) return false; if (lowerValue === true.toString()) return true; // is it a number if (isFinite(lowerValue) && lowerValue !== '') return new Number (lowerValue); // just leave it untouched but trimmed return value.trim(); } }Why not join our forum, follow the blog or follow me on Twitter to ensure you get updates when they are available.