Convert JSON to XML


There are a few examples of XML to JSON conversion around, but not so many going the the other way. In case you need to convert Apps Script objects to XML, here's a snippet to do it. Actually there are two approaches shown here, as dealing with Arrays is not an exact science in XML. I prefer the second of the solutions shown. You can find the opposite of this over at From Xml to JSON

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).
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <aString>some string</aString>
  <aNumber>8</aNumber>
  <aBoolean>false</aBoolean>
  <anObject>
    <apis>
      <element>
        <name>numbers</name>
        <url>http://numbersapi.com/</url>
      </element>
    </apis>
  </anObject>
  <anArray>
    <element>
      <value>8</value>
      <result>legs an arachnid has</result>
    </element>
    <element>
      <value>8</value>
      <result>furlongs in a mile</result>
    </element>
  </anArray>
  <anotherArray>
    <element>1</element>
    <element>2</element>
    <element>3</element>
  </anotherArray>
</root>


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 <element> to identify elements of an array. The problem with this approach is that the JSON is not reversible back to XML - since new tags have been inserted. A better approach is to use the Array key as the tag to be repeated. 

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
<root>
  <aString>some string</aString>
  <aNumber>8</aNumber>
  <aBoolean>false</aBoolean>
  <anObject>
    <apis>
      <name>numbers</name>
      <url>http://numbersapi.com/</url>
    </apis>
    <apis>
      <name>faa</name>
      <url>http://services.faa.gov/airport/status</url>
    </apis>
  </anObject>
  <anArray>
    <value>8</value>
    <result>legs an arachnid has</result>
  </anArray>
  <anArray>
    <value>8</value>
    <result>furlongs in a mile</result>
  </anArray>
  <anotherArray>1</anotherArray>
  <anotherArray>2</anotherArray>
  <anotherArray>3</anotherArray>
</root>

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;
}


For more like this, see Google Apps Scripts snippets. Why not join our forumfollow the blog or follow me on twitter to ensure you get updates when they are available. 

You want to learn Google Apps Script?

Learning Apps Script, (and transitioning from VBA) are covered comprehensively in my my book, Going Gas - from VBA to Apps script, available All formats are available now from O'Reilly,Amazon and all good bookshops. You can also read a preview on O'Reilly

If you prefer Video style learning I also have two courses available. also published by O'Reilly.
Google Apps Script for Developers and Google Apps Script for Beginners.






Comments