nkn
nkn

Reputation: 145

JSON to XML Using Javascript

I am trying to convert the JSON to XML but not getting exact output.In My JSON having array object it not converting that to XML array.Mainly array object is not converting into XML as expected

var InputJSON = "{"body":{"entry": [{ "fullURL" : "abcd","Resource": "1234"},{ "fullURL" : "efgh","Resource": "5678"}]}}";
var output = eval("OBJtoXML("+InputJSON+");")

function OBJtoXML(obj) {
    var xml = '';
    for (var prop in obj) {
        xml += "<" + prop + ">";
        if(obj[prop] instanceof Array) {
            for (var array in obj[prop]) {
                xml += OBJtoXML(new Object(obj[prop][array]));
            }
        } else if (typeof obj[prop] == "object") {
            xml += OBJtoXML(new Object(obj[prop]));
        } else {
            xml += obj[prop];
        }
        xml += "</" + prop + ">";
    }
    var xml = xml.replace(/<\/?[0-9]{1,}>/g,'');
    return xml
}

Actual Output:

<body>
  <entry>
    <fullURL>abcd</fullURL>
    <Resource>1234</Resource>
    <fullURL>efgh</fullURL>
    <Resource>5678</Resource>
  </entry>
</body>

Expected Output:

<body>
  <entry>
    <fullURL>abcd</fullURL>
    <Resource>1234</Resource>
  </entry>
 <entry>
    <fullURL>efgh</fullURL>
    <Resource>5678</Resource>
  </entry>
</body>

Please guide me if i am missing anything from the code to get my expected result

Upvotes: 12

Views: 55302

Answers (8)

Valentyn Kolesnikov
Valentyn Kolesnikov

Reputation: 2097

Xml-to-json library has methods jsonToXml(json) and xmlToJson(xml).

https://xmltojson.github.io

var inputJSON = '{"body":{"entry": [{ "fullURL" : "abcd","Resource": "1234"},{ "fullURL" : "efgh","Resource": "5678"}]}}';

var xml = jsonToXml(inputJSON);

// <?xml version="1.0" encoding="UTF-8"?>
// <body>
//   <entry>
//     <fullURL>abcd</fullURL>
//     <Resource>1234</Resource>
//   </entry>
//   <entry>
//     <fullURL>efgh</fullURL>
//     <Resource>5678</Resource>
//   </entry>
// </body>

Upvotes: 2

totymedli
totymedli

Reputation: 31182

Object/Array to XML converter

The following solution can turn a JS variable to a (non indented) XML string. It supports both lists (arrays) and objects.

  • Use objectToXml(object) to create a valid XML with a single root element.
  • Use variableToXml(variable, 'listElementName') if you want to convert an array of elements. In this case, you have to pass the tag name for the list elements as the second argument.
function objectToXml(object) {
  if (object instanceof Array || Object.keys(object).length !== 1) {
    throw 'variable has to be an object with a single property'
  }
  return variableToXml(object)
}

function variableToXml(variable, arrayItemPropertyName = null) {
  if (Array.isArray(variable)) {
    return variable.reduce((xml, propertyValue) => {
      const value = variableToXml(propertyValue)
      return `${xml}<${arrayItemPropertyName}>${value}</${arrayItemPropertyName}>`
    }, '')
  }
  if (variable instanceof Object) {
    return Object.entries(variable).reduce((xml, [propertyName, propertyValue]) => {
      const value = variableToXml(propertyValue, propertyName )
      const tag = propertyValue instanceof Array ? value : `<${propertyName}>${value}</${propertyName}>`
      return `${xml}${tag}`
    }, '')
  }
  return variable
}

Input variable

const object = {
  rootTag: {
    intProperty: 4,
    stringProperty: 'foo',
    listOfElements: {
      element: [{
        intProperty: 5,
        stringProperty: 'bar',
      }, {
        intProperty: 5,
        stringProperty: 'bar',
      }],
    },
    list: {
      listElement: [1, 2, 3],
    },
  },
}

Output XML (prettified)

<rootTag>
  <intProperty>4</intProperty>
  <stringProperty>foo</stringProperty>
  <listOfElements>
    <element>
      <intProperty>5</intProperty>
      <stringProperty>bar</stringProperty>
    </element>
    <element>
      <intProperty>5</intProperty>
      <stringProperty>bar</stringProperty>
    </element>
  </listOfElements>
  <list>
    <listElement>1</listElement>
    <listElement>2</listElement>
    <listElement>3</listElement>
  </list>
</rootTag>

Demo

const object = {
  rootTag: {
    intProperty: 4,
    stringProperty: 'foo',
    listOfElements: {
      element: [{
        intProperty: 5,
        stringProperty: 'bar',
      }, {
        intProperty: 5,
        stringProperty: 'bar',
      }],
    },
    list: {
      listElement: [1, 2, 3],
    },
  },
}

console.log(objectToXml(object))

function objectToXml(object) {
  if (object instanceof Array || Object.keys(object).length !== 1) {
    throw 'variable has to be an object with a single property'
  }
  return variableToXml(object)
}

function variableToXml(variable, arrayItemPropertyName = null) {
  if (Array.isArray(variable)) {
    return variable.reduce((xml, propertyValue) => {
      const value = variableToXml(propertyValue)
      return `${xml}<${arrayItemPropertyName}>${value}</${arrayItemPropertyName}>`
    }, '')
  }
  if (variable instanceof Object) {
    return Object.entries(variable).reduce((xml, [propertyName, propertyValue]) => {
      const value = variableToXml(propertyValue, propertyName )
      const tag = propertyValue instanceof Array ? value : `<${propertyName}>${value}</${propertyName}>`
      return `${xml}${tag}`
    }, '')
  }
  return variable
}

Upvotes: 0

Emanuel
Emanuel

Reputation: 3277

Using xml-js lib

import { json2xml } from "xml-js";

const input = {
  contact: {
    name: `John & cia "example"`
  }
};
const xml = json2xml(input, {
  compact: true
});

// <contact><name>John &amp; cia \"example\"</name></contact>

https://codesandbox.io/s/xml-json-forked-zgit4?file=/src/index.js:97-103

:)

Upvotes: 5

cyutSmile
cyutSmile

Reputation: 1

const objectToXml = (object) => Object.keys(object).reduce((reqStr, key) => {
  const value = object[key] || '';
  const isObject = typeof value === 'object';
  const isArray = Array.isArray(value);
  if (isArray) {
    return reqStr + value.reduce((accumulator, currentValue) =>
      accumulator + `<${key}>${ typeof currentValue === 'object' ? objectToXml(currentValue) : (currentValue || '')}</${key}>`
    ,'');
  }
  if (isObject) {
    return reqStr + `<${key}>${objectToXml(value)}</${key}>`;
  }
  return reqStr + `<${key}>${value}</${key}>`;
}, '');       

const output = objectToXml(yourJson);
console.log(output);

Upvotes: 0

Jcc.Sanabria
Jcc.Sanabria

Reputation: 691

function OBJtoXML(obj, index) {
    var xml = '', 
        root, 
        count = 0;
    if (index > 0) count = index;
    for (var prop in obj) {
      switch (typeof obj[prop]) {
          case 'object': {
              if(obj[prop] instanceof Array) {
                  for (var instance in obj[prop]) {
                    xml += `\n\t<${prop}>\n${OBJtoXML(new Object(obj[prop][instance]))}\t</${prop}>`;
                  }
              }
              else {
                  if (count === 0) {
                    // console.log(`Setting root: ${prop}`)
                    root = prop
                  }
                  xml += `<${prop}>${OBJtoXML(new Object(obj[prop]), count)}\n</${prop}>\n`;
              }
              break;
          }
          case 'number':
          case 'string': {
              // console.log(`Setting ${typeof obj[prop]}`)
              xml += `\t\t<${prop}>${obj[prop]}</${prop}>\n`;
              break;
          }
      }
      count += 1;
    }
    return xml
}

var InputJSON = '{"body":{"entry": [{ "fullURL" : "abcd","Resource": "1234"},{ "fullURL" : "efgh","Resource": "5678"}]}}';
var output = eval("OBJtoXML("+InputJSON+");");
console.log(output);

Upvotes: 0

Andrei Rosu
Andrei Rosu

Reputation: 1417

var inputJSON = '{"body":{"entry": [{ "fullURL" : "abcd","Resource": "1234"},{ "fullURL" : "efgh","Resource": "5678"}]}}';
var parsedInput = JSON.parse(inputJSON);

function OBJtoXML(obj) {
    var xml = '';
    for (var prop in obj) {
        if (obj[prop] instanceof Array) {
            for (var array in obj[prop]) {
                xml += '<' + prop + '>';
                xml += OBJtoXML(new Object(obj[prop][array]));
                xml += '</' + prop + '>';
            }
        } else {
            xml += '<' + prop + '>';
            typeof obj[prop] == 'object' ? xml += OBJtoXML(new Object(obj[prop])) : xml += obj[prop];
            xml += '</' + prop + '>';
        }
    }
    var xml = xml.replace(/<\/?[0-9]{1,}>/g, '');
    return xml;
}

Upvotes: 1

Usman Wali
Usman Wali

Reputation: 417

replace your OBJtoXML function with

function OBJtoXML(obj) {
  var xml = '';
  for (var prop in obj) {
    xml += obj[prop] instanceof Array ? '' : "<" + prop + ">";
    if (obj[prop] instanceof Array) {
      for (var array in obj[prop]) {
        xml += "<" + prop + ">";
        xml += OBJtoXML(new Object(obj[prop][array]));
        xml += "</" + prop + ">";
      }
    } else if (typeof obj[prop] == "object") {
      xml += OBJtoXML(new Object(obj[prop]));
    } else {
      xml += obj[prop];
    }
    xml += obj[prop] instanceof Array ? '' : "</" + prop + ">";
  }
  var xml = xml.replace(/<\/?[0-9]{1,}>/g, '');
  return xml
}

Upvotes: 16

scagood
scagood

Reputation: 782

There are a few problems here, for starters, here the JSON string variable either needs to have it's quotes escaped. Or be wrapped in single quotes. For example:

var InputJSON = '{"body":{"entry": [{ "fullURL" : "abcd","Resource": "1234"},{ "fullURL" : "efgh","Resource": "5678"}]}}';

Next, there is no need to use eval here, when using JSON in JavaScript you should use JSON.parse

// First parse the JSON
var InputJSON = JSON.parse(InputJSON);

// Now execute the 'OBJtoXML' function
var output = OBJtoXML(InputJSON);

Now we come to the meat of this question, why is entry only occuring once? The problem that you're having is that xml += "<" + prop + ">"; and xml += "</" + prop + ">"; are only happening once per property. A possible solution would look like this:

function OBJtoXML(obj) {
    var xml = '';
    for (var prop in obj) {
        xml += "<" + prop + ">";
        if(Array.isArray(obj[prop])) {
            for (var array of obj[prop]) {

                // A real botch fix here
                xml += "</" + prop + ">";
                xml += "<" + prop + ">";

                xml += OBJtoXML(new Object(array));
            }
        } else if (typeof obj[prop] == "object") {
            xml += OBJtoXML(new Object(obj[prop]));
        } else {
            xml += obj[prop];
        }
        xml += "</" + prop + ">";
    }
    var xml = xml.replace(/<\/?[0-9]{1,}>/g,'');
    return xml
}

Upvotes: 3

Related Questions