web-dev-qa-db-ja.com

Nodeを使用してURLからXMLを解析する方法

node-xml2js を使用してXMLを解析しています。 URLからXMLを解析できません。私はこれを SO answer をモデルとして使用しました。しかし、以下のコードを使用すると、結果としてnullが返されます。私が間違っていることについて何か考えはありますか?

更新:xmlのURLを実際に使用されているサイトに更新しました。

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

Xml2jsがチャンクごとにxmlを解析できないので、http応答全体をバッファリングする必要があります。そのために、ここではグローバルを使用しましたが、_concat-stream_のようなものを使用することをお勧めします(後でそれを投稿します)。

私はこれを試しました、そしてそれは私のために働きます:

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

応答の送信が終了したときのみ、XMLを解析します。 _xml2js_はsaxを使用します。これはストリーミングをサポートしているようですが、_xml2js_がそれを利用しているかどうかは不明です。

チャンクごとの解析(例と同様)を使用する小さな例を作成しましたが、チャンク内に無効なxmlが到着するため、解析時にエラーが発生して失敗します。そのため、応答全体をバッファリングする必要があります。

XMLが非常に大きい場合は、saxのような、ストリームをサポートする別のパーサーを試してください。

errorハンドラーをparserに追加して、エラーが発生した場合にエラーを出力することもできます。

連結ストリーム

連結ストリームを使用すると、すべての.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);
      });
    }));

});
_

saxを使用してファイル全体をバッファーしないようにすることができます(xmlファイルが大きい場合)が、より低レベルですが、ストリームとしてのパイプは非常に似ています。

20
edin-m

あなたの質問に基づいて、解決策はこのようなものでなければなりません。

どちらのオプションも期待どおりに機能し、xmlの有効なjsonオブジェクトを提供します。 xml2jsのread.meで説明されているように、xmlを解析する方法を設定できます。

ネイティブ


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 [〜#〜] *コールバック地獄なし


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.');
    }
});
4
Ferry Kobus

xml2jsを使用すると、非常に簡単です。

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