Question

I have a multi-dimensional Javascript Object that I can easily convert to a JSON string using a .stringify method. I'm trying to write a function to do something similar but in an XML, markup, format. The catch is I want it to be able to handle any number of dimensions.

Let's say I have the following the multi-dimensional object with values like so:

object['annualrevenues']['option0']['ID'] = 1;
object['annualrevenues']['option0']['text'] = '$50mil';
object['annualrevenues']['option1']['ID'] = 2;
object['annualrevenues']['option1']['text'] = '$100mil';
object['annualrevenues']['option2']['ID'] = 3;
object['annualrevenues']['option2']['text'] = '$200mil';

I want to build a string like so:

var xmlText = <xml><annualrevenues><option0><ID>1</ID><text>$50</text></option0></annualrevenues></xml>

That once returned as a response with contentType 'XMLDOC' will look like this:

<xml>
  <annualrevenues>
    <option0>
      <ID>1</ID>
      <text>$50</text>
    </option0>
  </annualrevenues>
</xml>

So I have the following function:

var xmlText = '<xml>';
    xmlText += formatXMLSubObjects(objText,xmlText);

function formatXMLSubObjects(objText,xmlText){
  for (prop in objText) {
    if (typeof objText[prop] == 'object') {
        xmlText += '<'+prop+'>';
        for (subProp in objText[prop]) {
            if (typeof objText[prop][subProp] == 'object') {
                // Run the function again as recursion
                xmlText += formatXMLSubObjects(objText[prop][subProp],xmlText);
            }
            else {
                xmlText += '<' + subProp + '>' + objText[prop][subProp] + '</' + subProp + '>';
            }
        }
        xmlText += '</'+prop+'>';
    }
    else {
        xmlText += '<'+prop+'>'+objText[prop]+'</'+prop+'>';
    }
  }
return xmlText;
}

The problem is when the formatXMLSubObjects function returns from the second call, the original object in the first call has been overwritten and is now undefined.

Anyone able to help with this?

Was it helpful?

Solution

Move the definition of xmlText inside the function and use another variable outside to contain the initial payload, and also local variables in the for loops, otherwise they are considered global and overwritten, and don't pass your xmlText ahead to the call, but simply concatenate the result with the previous one every time.

function formatXMLSubObjects(objText) {
   var xmlText = ""; // this will contain only this chunk of the object

   for (var prop in objText) {
      xmlText += '<'+prop+'>'; // place the tag anyway
      if (typeof objText[prop] == 'object') {
            xmlText += formatXMLSubObjects(objText[prop]); // if it's an object recurse
      } else {
            xmlText += objText[prop]; // ... otherwise just add the value (this will work only for simple values
      }
   xmlText += '</' + prop + '>';
   }
   return xmlText;
}

var xml = '<xml>';
xml += formatXMLSubObjects(obj);
xml += '</xml>';

Take a look at this fiddle: http://jsfiddle.net/vZjAP/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top