3

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!

0

4 Answers 4

4

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);```
Sign up to request clarification or add additional context in comments.

Comments

2

var custFName = result['soapenv:Envelope']['soapenv:Body'][0]['int:realURLHe‌​re'][0]['response'][‌​0]['cust'][0]['fName‌​'];

This solved my problem. My struggles had to do with this response having everything in an array. If there is an easier way to do this or something more dynamic, please let me know. But for now, this worked.

2 Comments

Try the below answer
Thanks rocketlobster. Was having trouble navigating through the XML dom, didn't include the first element with the colon, in your case, the ['soapenv:Envelope'] and also the [0] for every element. Thanks!
0

Try this

const transform = require('camaro')

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

const template = {
    fname: '//cust/fName'
}

const result = transform(xml, template)
console.log(JSON.stringify(result, null, 2))

Which print out

{
  "fname": "hello world"
}

You can access by using result.fname

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.