简体   繁体   中英

Node.js xml2js http.request tag matching

I am trying to work with XML data from an https.request and display it to a web page in table format. I'm trying to follow this tutorial which describes what I would like to do very well: https://programmerblog.net/parse-xml-using-nodejs/

However, I am having an issue filtering the results of XML.

Here is my code:

// MODULES - INCLUDES
var xml2js = require('xml2js');
var parser = new xml2js.Parser();

module.exports = function (app) {
  // FORM - SUBMIT - CUCMMAPPER
  app.post('/cucmmapper/submit', function (req, res) {

    // FORM - DATA COLLECTION
    var cucmpub = req.body.cucmpub;
    var cucmversion = req.body.cucmversion;
    var username = req.body.username;
    var password = req.body.password;

    // JS - VARIABLE DEFINITION
    var authentication = username + ":" + password;
    var soapreplyx = '';
    var cssx = '';

    // HTTP.REQUEST - BUILD CALL
    var https = require("https");
    var headers = {
      'SoapAction': 'CUCM:DB ver=' + cucmversion + ' listCss',
      'Authorization': 'Basic ' + new Buffer(authentication).toString('base64'),
      'Content-Type': 'text/xml; charset=utf-8'
    };

    // SOAP - AXL CALL
    var soapBody = new Buffer('<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/11.5">' +
      '<soapenv:Header/>' +
      '<soapenv:Body>' +
      '<ns:listCss sequence="?">' +
      '<searchCriteria>' +
      '<name>%</name>' +
      '</searchCriteria>' +
      '<returnedTags uuid="?">' +
      '<name>?</name>' +
      '<description>?</description>' +
      '<clause>?</clause>' +
      '</returnedTags>' +
      '</ns:listCss>' +
      '</soapenv:Body>' +
      '</soapenv:Envelope>');

    // HTTP.REQUEST - OPTIONS
    var options = {
      host: cucmpub, // IP ADDRESS OF CUCM PUBLISHER
      port: 8443, // DEFAULT CISCO SSL PORT
      path: '/axl/', // AXL URL
      method: 'POST', // AXL REQUIREMENT OF POST
      headers: headers, // HEADER VAR
      rejectUnauthorized: false // REQUIRED TO ACCEPT SELF-SIGNED CERTS
    };

    // HTTP.REQUEST - Doesn't seem to need this line, but it might be useful anyway for pooling?
    options.agent = new https.Agent(options);

    // HTTP.REQUEST - OPEN SESSION
    let soapRequest = https.request(options, soapResponse => {
      soapResponse.setEncoding('utf8');
      soapResponse.on('data', chunk => {
        soapreplyx += chunk
      });
      // HTTP.REQUEST - RESULTS + RENDER
      soapResponse.on('end', () => {
        console.log(soapreplyx);
        parser.parseString(soapreplyx, function (err, result) {
          // console.dir(result);
          var cssx = result['soapenv']['ns']['return']['css'];
          console.log(cssx);
          res.render('cucmmapper-results.html', {
            title: 'CUCM 2.1',
            soapreply: soapreplyx,
            css: cssx,
          });
        });
      });
    });

    // SOAP - SEND AXL CALL
    soapRequest.write(soapBody);
    soapRequest.end();
  });
}

I am specifically getting the following console error.

TypeError: Cannot read property 'ns' of undefined
    at C:\Users\PetersonA16\Desktop\listlineapp\listlineapp\routes\cucmmapper.js:68:39

The result of the following:

console.log(soapreplyx);

Replies back with this (edited) data.

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns:listCssResponse xmlns:ns="http://www.cisco.com/AXL/API/11.0">
<return>
<css uuid="{E85C54E1-5737-7516-FFFC-14E97B1D0504}">
<description>description1</description>
<clause>something1</clause>
<name>name1</name>
</css>
<css uuid="{AFFC55A7-CD16-E250-09E8-9A12ABBE0C9E}">
<description>description2</description>
<clause>something2</clause>
<name>name2</name>
</css>
</return>
</ns:listCssResponse>
</soapenv:Body>
</soapenv:Envelope>

If I un-comment out the line:

console.dir(result);

I do get the following console output:

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

My theory is that I need to use an xml2js option. After some experimentation though, I haven't been able to make any headway.

I'm still new to JS, so any help, pointer, or suggestions would be greatly appreciated!

if you want to get all css nodes, you can try this

const transform = require('camaro')

const xml = `
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns:listCssResponse xmlns:ns="http://www.cisco.com/AXL/API/11.0">
<return>
<css uuid="{E85C54E1-5737-7516-FFFC-14E97B1D0504}">
<description>description1</description>
<clause>something1</clause>
<name>name1</name>
</css>
<css uuid="{AFFC55A7-CD16-E250-09E8-9A12ABBE0C9E}">
<description>description2</description>
<clause>something2</clause>
<name>name2</name>
</css>
</return>
</ns:listCssResponse>
</soapenv:Body>
</soapenv:Envelope>
`

const json = transform(xml, {
    css: ['//css', {
        uuid: '@uuid',
        name: 'name',
        description: 'description',
        clause: 'clause'
    }]
})

console.log(json.css)

Output:

[ { clause: 'something1',
    description: 'description1',
    name: 'name1',
    uuid: '{E85C54E1-5737-7516-FFFC-14E97B1D0504}' },
  { clause: 'something2',
    description: 'description2',
    name: 'name2',
    uuid: '{AFFC55A7-CD16-E250-09E8-9A12ABBE0C9E}' } ]

As a note, I did get it to work with xml2js. Here is my code.

// MODULES - INCLUDES
var xml2js = require('xml2js');
var parser = new xml2js.Parser();

module.exports = function (app) {
  // FORM - SUBMIT - CUCMMAPPER
  app.post('/cucmmapper/submit', function (req, res) {

    // FORM - DATA COLLECTION
    var cucmpub = req.body.cucmpub;
    var cucmversion = req.body.cucmversion;
    var username = req.body.username;
    var password = req.body.password;

    // JS - VARIABLE DEFINITION
    var authentication = username + ":" + password;
    var soapreplyx = '';
    var cssx = '';
    var spacer = '-----';
    var rmline1 = '';
    var rmline2 = '';
    var rmline3 = '';
    var rmline4 = '';
    var rmbottomup1 = '';
    var rmbottomup2 = '';
    var rmbottomup3 = '';

    // HTTP.REQUEST - BUILD CALL
    var https = require("https");
    var headers = {
      'SoapAction': 'CUCM:DB ver=' + cucmversion + ' listCss',
      'Authorization': 'Basic ' + new Buffer(authentication).toString('base64'),
      'Content-Type': 'text/xml; charset=utf-8'
    };

    // SOAP - AXL CALL
    var soapBody = new Buffer('<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/11.5">' +
      '<soapenv:Header/>' +
      '<soapenv:Body>' +
      '<ns:listCss sequence="?">' +
      '<searchCriteria>' +
      '<name>%</name>' +
      '</searchCriteria>' +
      '<returnedTags uuid="?">' +
      '<name>?</name>' +
      '<description>?</description>' +
      '<clause>?</clause>' +
      '</returnedTags>' +
      '</ns:listCss>' +
      '</soapenv:Body>' +
      '</soapenv:Envelope>');

    // HTTP.REQUEST - OPTIONS
    var options = {
      host: cucmpub, // IP ADDRESS OF CUCM PUBLISHER
      port: 8443, // DEFAULT CISCO SSL PORT
      path: '/axl/', // AXL URL
      method: 'POST', // AXL REQUIREMENT OF POST
      headers: headers, // HEADER VAR
      rejectUnauthorized: false // REQUIRED TO ACCEPT SELF-SIGNED CERTS
    };

    // HTTP.REQUEST - Doesn't seem to need this line, but it might be useful anyway for pooling?
    options.agent = new https.Agent(options);

    // HTTP.REQUEST - OPEN SESSION
    let soapRequest = https.request(options, soapResponse => {
      soapResponse.setEncoding('utf8');
      soapResponse.on('data', chunk => {
        soapreplyx += chunk
      });
      // HTTP.REQUEST - RESULTS + RENDER
      soapResponse.on('end', () => {

        // EDIT - SCRUB XML OUTPUT
        var rmline1 = soapreplyx.replace(/<\?xml\sversion='1\.0'\sencoding='utf-8'\?>/g, '');
        var rmline2 = rmline1.replace(/<soapenv:Envelope\sxmlns:soapenv="http:\/\/schemas.xmlsoap.org\/soap\/envelope\/">/g, '');
        var rmline3 = rmline2.replace(/<soapenv:Body>/g, '');
        var rmline4 = rmline3.replace(/<ns:listCssResponse\sxmlns:ns="http:\/\/www\.cisco\.com\/AXL\/API\/[0-9]*\.[0-9]">/g, '');
        var rmbottomup1 = rmline4.replace(/<\/soapenv:Envelope>/g, '');
        var rmbottomup2 = rmbottomup1.replace(/<\/soapenv:Body>/g, '');
        var xmlscrubbed = rmbottomup2.replace(/<\/ns:listCssResponse>/g, '');
        // console.log(xmlscrubbed);
        // console.log(spacer);

        // XML2JS - TESTING
        parser.parseString(xmlscrubbed, function (err, result) {
          var cssx = result['return']['css'];
        //   console.log(cssx);
        //   console.log(spacer);
          res.render('cucmmapper-results.html', {
            title: 'CUCM 2.0',
            cucmpub: cucmpub,
            cssx: cssx,
            soapreply: soapreplyx,
            xmlscrubbed: xmlscrubbed
          });
        });
      });
    });

    // SOAP - SEND AXL CALL
    soapRequest.write(soapBody);
    soapRequest.end();
  });
}

Here is my HTML table.

<div class="row">
                    <div class="col-md-12" class="pull-left">
                        <table class="table table-hover table-condensed">
                            <thread>
                                <tr>
                                    <th>CSS</th>
                                    <th>DESCRIPTION</th>
                                    <th>PARTITIONS</th>
                                </tr>
                            </thread>
                            <tbody>
                                {{#each cssx}}
                                <tr>
                                    <td>{{this.name}}</td>
                                    <td>{{this.description}}</td>
                                    <td>{{this.clause}}</td>
                                </tr>
                                {{/each}}
                            </tbody>
                        </table>
                    </div>
                </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM