web-dev-qa-db-fra.com

Comment analyser XML à partir d'URL avec Node

J'utilise node-xml2js pour analyser XML. Je ne parviens pas à analyser XML à partir d'une URL. J'ai utilisé cette SO réponse comme modèle. Mais lorsque j'utilise le code ci-dessous, le résultat est null. Des idées sur ce que je fais mal?

UPDATE: J'ai mis à jour l'URL du fichier XML au site réel utilisé.

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

Je ne vois pas xml2js être en mesure d'analyser le xml avec ses morceaux, nous devons donc mettre en tampon toute la réponse http. Pour ce faire, j'ai utilisé global ici, mais il vaut mieux utiliser quelque chose comme concat-stream (je le posterai plus tard).

J'ai essayé celui-ci et ça marche pour moi:

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

Seulement lorsque la réponse est terminée, nous analysons XML. xml2js utilise sax qui semble prendre en charge le streaming mais ne sait pas si xml2js en profite.

J'ai créé un petit exemple qui utilise l'analyse par bloc (semblable à votre exemple), mais échoue en donnant une erreur lors de l'analyse car un xml invalide arrive - c'est pourquoi nous devons mettre en mémoire tampon la réponse entière.

Si votre fichier xml est très gros, essayez différents analyseurs tels que sax qui prennent en charge les flux.

Vous pouvez également ajouter le gestionnaire error à parser pour pouvoir imprimer les erreurs si elles les rencontrent.

Flux de concat

Avec concat stream, vous pouvez concaténer plus élégamment tous les appels .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);
      });
    }));

});

Vous pouvez utiliser sax pour ne pas mettre en mémoire tampon la totalité du fichier (au cas où vos fichiers xml seraient volumineux), mais il s'agit d'un niveau plus bas, mais la canalisation en tant que flux est très similaire.

16
edin-m

Sur la base de votre question, la solution devrait ressembler à ceci.

Les deux options fonctionnent comme prévu et donnent un objet json valide du fichier xml . Vous pouvez configurer comment analyser le fichier XML comme décrit dans le read.me de xml2js.

Originaire de


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* Sans l'enfer de rappel


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

Avec xml2js, c'est très simple.

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