Home > database >  Converting XML to JSON in JS
Converting XML to JSON in JS

Time:03-19

I just recently started learning js and trying to solve the problem of converting xml source file

<ns1:input xmlns:ns1="ns1:test" xmlns:ns2="ns2:test">
    <ns1:element id="1">
        <ns2:field1>1</ns2:field1>
        <ns2:field2>2</ns2:field2>
        <ns2:field3>3</ns2:field3>
    </ns1:element>
    <ns1:element id="2">
        <ns2:field1>4</ns2:field1>
        <ns2:field2>5</ns2:field2>
        <ns2:field3>6</ns2:field3>
    </ns1:element>
</ns1:input>

to json of the following content

{
   "elements":[
      {
         "element":{
            "field1":"1",
            "field2":"2",
            "field3":"3",
            "id":"1"
         }
      },
      {
         "element":{
            "field1":"4",
            "field2":"5",
            "field3":"6",
            "id":"2"
         }
      }
   ]
}

using javascript. I tried to solve the problem using the xml2json library - it turned out not quite what I needed. Can you please tell me how this can be implemented?

Below is code and output

var convert = require('xml-js');
var xml =
    '<ns1:input xmlns:ns1="ns1:test" xmlns:ns2="ns2:test">' 
    '<ns1:element id="1">' 
        '<ns2:field1>1</ns2:field1>' 
        '<ns2:field2>2</ns2:field2>' 
        '<ns2:field3>3</ns2:field3>'  
    '</ns1:element>' 
    '<ns1:element id="2">' 
        '<ns2:field1>4</ns2:field1>' 
        '<ns2:field2>5</ns2:field2>' 
        '<ns2:field3>6</ns2:field3>' 
    '</ns1:element>' 
    '</ns1:input>';
var result2 = convert.xml2json(xml, {compact: true, spaces: 2, ignoreAttributes:true});
console.log(result2);

result

{
  "ns1:input": {       
    "ns1:element": [   
      {
        "ns2:field1": {
          "_text": "1" 
        },
        "ns2:field2": {
          "_text": "2" 
        },
        "ns2:field3": {
          "_text": "3" 
        }
      },
      {
        "ns2:field1": {
          "_text": "4"
        },
        "ns2:field2": {
          "_text": "5"
        },
        "ns2:field3": {
          "_text": "6"
        }
      }
    ]
  }
}

CodePudding user response:

Try lib named x2js

    var x2js = new X2JS();
    var xmlText = "your_xml_string";
    var jsonObj = x2js.xml_str2json( xmlText );

For more documentation refer to github page

CodePudding user response:

Rather then doing a generic convert you can read the XML using DOM Xpath and build up the JSON. The main benefit is that the JSON structure does not directly depend on the XML structure.

This works in any modern browser, in node.js you need the xmldom and xpath packages.

// provide namespace resolution for the Xpath expressions
const resolver = function(prefix) {
    const namespaces = {
        n1: 'ns1:test',
        n2: 'ns2:test'
    }
    return namespaces[prefix || ''] || null;
}

const data = new DOMParser().parseFromString(getXMLString(), 'text/xml');
// fetch "{ns1:test}element" nodes 
const elementNodes = data.evaluate(
    "//n1:element", data, resolver, XPathResult.ANY_TYPE, null
);
let elementNode;
const elements = [];
while (elementNode = elementNodes.iterateNext()) {
  const element = {
    // read the id attribute
    id: elementNode.getAttribute('id'),
    // fetch the text contents of the first "{ns2:test}field1"
    // note the string cast in the expression
    field1: data.evaluate(
      'string(n2:field1)', elementNode, resolver, XPathResult.STRING_TYPE, null
    ).stringValue,
    field2: data.evaluate(
      'string(n2:field2)', elementNode, resolver, XPathResult.STRING_TYPE, null
    ).stringValue,
    field3: data.evaluate(
      'string(n2:field3)', elementNode, resolver, XPathResult.STRING_TYPE, null
    ).stringValue
  }
  elements.push({element});
}

console.log({elements});

function getXMLString() {
  return `<ns1:input xmlns:ns1="ns1:test" xmlns:ns2="ns2:test">
    <ns1:element id="1">
        <ns2:field1>1</ns2:field1>
        <ns2:field2>2</ns2:field2>
        <ns2:field3>3</ns2:field3>
    </ns1:element>
    <ns1:element id="2">
        <ns2:field1>4</ns2:field1>
        <ns2:field2>5</ns2:field2>
        <ns2:field3>6</ns2:field3>
    </ns1:element>
</ns1:input>
`;
}

  • Related