it-swarm.dev

Come analizzare XML da URL con nodo

Sto usando node-xml2js per analizzare XML. Sto riscontrando problemi nell'analisi di XML da un URL. Ho usato questo SO answer come modello. Ma quando uso il codice qui sotto, ottengo null come risultato. Qualche idea su cosa sto facendo male?

AGGIORNAMENTO: ho aggiornato l'url per l'xml al sito effettivo utilizzato.

var eyes = require('eyes');
var https = require('https');
var fs = require('fs');
var xml2js = require('xml2js');
var parser = new xml2js.Parser();

parser.addListener('end', function(result) {
  eyes.inspect(result);
  console.log('Done.');
});

https.get('https://tsdrapi.uspto.gov/ts/cd/casestatus/sn78787878/info.xml', function(result) {
  result.on('data', function (data) {
    parser.parseString(data);
    });
  }).on('error', function(e) {
  console.log('Got error: ' + e.message);
});
13
Ken

Non vedo che xml2js sia in grado di analizzare xml con i suoi blocchi, quindi abbiamo bisogno di bufferizzare l'intera risposta http. Per farlo ho usato global qui, ma è meglio usare qualcosa come concat-stream (lo posterò qualche volta dopo).

Ho provato questo e funziona per me:

 var eyes = require('eyes');
 var https = require('https');
 var fs = require('fs');
 var xml2js = require('xml2js');
 var parser = new xml2js.Parser();

 parser.on('error', function(err) { console.log('Parser error', err); });

 var data = '';
 https.get('https://tsdrapi.uspto.gov/ts/cd/casestatus/sn78787878/info.xml', function(res) {
     if (res.statusCode >= 200 && res.statusCode < 400) {
       res.on('data', function(data_) { data += data_.toString(); });
       res.on('end', function() {
         console.log('data', data);
         parser.parseString(data, function(err, result) {
           console.log('FINISHED', err, result);
         });
       });
     }
   });

Solo quando la risposta termina l'invio, quindi analizziamo XML. xml2js utilizza sax che sembra avere supporto per lo streaming ma non è sicuro che xml2js ne approfitti.

Ho creato un piccolo esempio che utilizza l'analisi chunk-by-chunk (simile al tuo esempio) ma non riesce a dare errori durante l'analisi perché in un chunk non valido arriva xml - ecco perché abbiamo bisogno di bufferare l'intera risposta.

Se il tuo xml è molto grande, prova diversi parser come sax che hanno il supporto del flusso.

Puoi anche aggiungere il gestore error a parser per poter stampare errori se li incontra.

Flusso Concat

Con concat stream puoi conciliare più elegantemente tutte le chiamate .on('data'...):

var https = require('https');
var xml2js = require('xml2js');
var parser = new xml2js.Parser();
var concat = require('concat-stream');

parser.on('error', function(err) { console.log('Parser error', err); });

https.get('https://tsdrapi.uspto.gov/ts/cd/casestatus/sn78787878/info.xml', function(resp) {

    resp.on('error', function(err) {
      console.log('Error while reading', err);
    });

    resp.pipe(concat(function(buffer) {
      var str = buffer.toString();
      parser.parseString(str, function(err, result) {
        console.log('Finished parsing:', err, result);
      });
    }));

});

Puoi usare sax per non essere in grado di bufferizzare l'intero file (nel caso in cui i tuoi file xml siano grandi), ma è più basso, tuttavia, il piping come stream è molto simile.

16
edin-m

In base alla tua domanda, la soluzione dovrebbe essere qualcosa di simile.

Entrambe le opzioni funzionano come previsto e forniscono un oggetto json valido di xml . Puoi configurare come analizzare l'xml come descritto nel file read.me di xml2js

Nativo


var eyes = require('eyes'),
    https = require('https'),
    fs = require('fs'),
    xml2js = require('xml2js'),
    parser = new xml2js.Parser();


https.get('https://tsdrapi.uspto.gov/ts/cd/casestatus/sn78787878/info.xml', function(res) {
    var response_data = '';
    res.setEncoding('utf8');
    res.on('data', function(chunk) {
        response_data += chunk;
    });
    res.on('end', function() {
        parser.parseString(response_data, function(err, result) {
            if (err) {
                console.log('Got error: ' + err.message);
            } else {
                eyes.inspect(result);
                console.log('Done.');
            }
        });
    });
    res.on('error', function(err) {
        console.log('Got error: ' + err.message);
    });
});

ASYNC* Senza il callback dell'inferno


var eyes = require('eyes'),
    https = require('https'),
    async =require('async'),
    xml2js = require('xml2js');

async.waterfall([
    function(callback) {
        https.get('https://tsdrapi.uspto.gov/ts/cd/casestatus/sn78787878/info.xml', function(res) {
            var response_data = '';
            res.setEncoding('utf8');
            res.on('data', function(chunk) {
                response_data += chunk;
            });
            res.on('end', function() {
                callback(null, response_data)
            });
            res.on('error', function(err) {
                callback(err);
            });
        });
    },
    function(xml, callback) {
        var parser = new xml2js.Parser();
        parser.parseString(xml, function(err, result) {
            if (err) {
                callback(err);
            } else {
                callback(null, result);
            }
        });
    }, 
    function(json, callback) {
        // do something usefull with the json
        eyes.inspect(json);
        callback();
    }
], function(err, result) {
    if (err) {
        console.log('Got error');
        console.log(err);
    } else {
        console.log('Done.');
    }
});
3
Ferry Kobus

Utilizzando xml2js, è molto semplice.

var parseString = require('xml2js').parseString;

var xmldata = "XML output from the url";
console.log(xmldata);
parseString(xmldata, function (err, result) {
 // Result contains XML data in JSON format
});
2
Abdul Manaf
var https = require('https');
var parseString = require('xml2js').parseString;
var xml = '';

function xmlToJson(url, callback) {
  var req = https.get(url, function(res) {
    var xml = '';

    res.on('data', function(chunk) {
      xml += chunk;
    });

    res.on('error', function(e) {
      callback(e, null);
    }); 

    res.on('timeout', function(e) {
      callback(e, null);
    }); 

    res.on('end', function() {
      parseString(xml, function(err, result) {
        callback(null, result);
      });
    });
  });
}

var url = "https://tsdrapi.uspto.gov/ts/cd/casestatus/sn78787878/info.xml"

xmlToJson(url, function(err, data) {
  if (err) {
    // Handle this however you like
    return console.err(err);
  }

  // Do whatever you want with the data here
  // Following just pretty-prints the object
  console.log(JSON.stringify(data, null, 2));
});
1
Chris