Parsing with xml2js

Viewed 4809

I am new to node.js and need to parse XML. In js, I just use a DOMParser and use getElementsByTagName to get the values I desire. I have just switched to node and am using xml2js (willing to consider alternatives). I have not been able to figure out how to parse through the response to get what I am looking for.

Code below:

function parseBody(body){
    var parseString = require('xml2js').parseString;
    var xml = body
    parseString(xml, function (err, result) {
    console.dir(result);
});

and here is the XML I am passing into the function:

<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:int=\"realURLHere">
   <soapenv:Header/>
   <soapenv:Body>
      <int:readResponse>
         <response>
            <request>?</request>
            <cust>
               <fName>?</fName>
            </cust>
        </response>
      </int:readResponse>
   </soapenv:Body>
</soapenv:Envelope>

Here is the output of my function:

{ 'soapenv:Envelope':
   { '$':
      { 'xmlns:soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',
        'xmlns:int': 'realURLHere' },
     'soapenv:Body': [ [Object] ] 
   } 
}

I am trying to access the value of <fName> within <cust> but having no luck. Any help would be appreciated. Thanks!

4 Answers

If you set the xplicitArray option to false, when it parses it won't create those arrays where you didn't expect. Like this:

function parseBody(body) {
    var parseString = require('xml2js').parseString;

    const options = {
        explicitArray: false
    };

    var xml = body
    parseString(xml, options, function (err, result) {
        console.log("cust fname: " + result['soapenv:Envelope']['soapenv:Body']['int:readResponse']['response']['cust']['fName']);
    })
}
var input = '<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:int=\"realURLHere"><soapenv:Header/><soapenv:Body><int:readResponse><response><request>?</request><cust><fName>?</fName></cust></response></int:readResponse></soapenv:Body></soapenv:Envelope>';
parseBody(input);

Furthermore if you remove the prefixes it can get even cleaner:

function parseBody(body) {
    var parseString = require('xml2js').parseString;
    var stripNS = require('xml2js').processors.stripPrefix;

    const options = {
        tagNameProcessors: [stripNS],
        explicitArray: false
    };

    var xml = body
    parseString(xml, options, function (err, result) {
        console.log("cust fname: " + result.Envelope.Body.readResponse.response.cust.fName);
    })
}
var input = '<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:int=\"realURLHere"><soapenv:Header/><soapenv:Body><int:readResponse><response><request>?</request><cust><fName>?</fName></cust></response></int:readResponse></soapenv:Body></soapenv:Envelope>';
parseBody(input);```

If you're using NodeJS, I highly recommend xml2js & xml2js-xpath. Here is their sample code that really helped me in a pinch.

var xml2js = require("xml2js");
var xpath = require("xml2js-xpath");
 
xml2js.parseString('<root><element id="15">target</element></root>', function(err, json) {

  // find all elements: returns xml2js JSON of the element
  var matches = xpath.find(json, "//element");
 
  // find the first element, and get its id:
  var matches = xpath.evalFirst(json, "//element", "id");
});

Related