【问题标题】:How to parse XML from URL with Node如何使用 Node 从 URL 解析 XML
【发布时间】:2016-03-04 14:19:18
【问题描述】:

我正在使用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);
});

【问题讨论】:

  • 你有一个错字,应该是var https = require('https')。修复此问题后,它对我有用。
  • @Edin M 感谢您指出这一点。我忘记在故障排除后复制/粘贴之前修复它。不幸的是,我在尝试访问实际站点时仍然遇到同样的问题。
  • 端点再次可访问,我的回答有效。希望您满意

标签: xml node.js express xml-parsing


【解决方案1】:

我没有看到 xml2js 能够通过它的块来解析 xml,所以我们需要缓冲整个 http 响应。为此,我在这里使用了 global,但最好使用 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 以便能够在遇到错误时打印它们。

连接流

使用 concat 流,您可以更优雅地连接所有 .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 文件很大),但它的级别更低,但是将其作为流进行管道传输非常相似。

【讨论】:

  • 可能文件足够小,并在一个块中报告给.on('data', ...。较大的文件报告有多个块。这是因为 tcp 是一个流式协议,底层实现一有它就给了我们块。何时和如何以及块大小的详细信息是实现的问题。
  • 我将使用许多其他非常大的文件。您的两个示例都缓冲整个文件吗?我认为 xml2js 充分利用了 sax。所以我有点困惑。
  • @Ken,是的。我建议直接使用sax 以便能够使用流支持,因为xml2js 没有利用它。有一个 opened issue 用于流支持。
  • res.statusCode >= 200 && res.statusCode
【解决方案2】:

根据您的问题,解决方案应该是这样的。

这两个选项都按预期工作,并提供了一个有效的 json xml 对象。 您可以按照 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.');
    }
});

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 我无法让您的代码正确显示 xml。
    【解决方案4】:
    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));
    });
    

    【讨论】:

    • 嘿,您可以在此处查看完整说明:antrikshy.com/blog/fetch-xml-url-convert-to-json-nodejs 我只是将协议从 http 更改为 https,以便从原始问题所依据的 url 中获取 xml。
    • @Chris,在您的链接上可以查看的所有内容都是 404 错误页面,其中包含一些关于您可以做些什么来找到您要查找的内容的散文。这就是为什么最好在这里解释一下。 (顺便说一下,页面仍然存在(当前),试试不带斜杠:antrikshy.com/blog/fetch-xml-url-convert-to-json-nodejs
    【解决方案5】:

    推荐你使用libarayrequest,代码很简单。然后您还可以使用 libaray cheerio 以及您需要从中提取任何信息以进行进一步处理。

    var request = require('request');
    const cheerio = require('cheerio');
    
    request('https://tsdrapi.uspto.gov/ts/cd/casestatus/sn78787878/info.xml', function (error, response, html) {
        if (!error && response.statusCode == 200) {
            // Do something you need
            var $ = cheerio.load(html, {
                xmlMode: true
            });
        const nodes = $('div');  // Just an example
        }
    });
    

    【讨论】:

      【解决方案6】:
      var Request = require("request");
      const express = require("express");
      const app = express();
      app.use(express.urlencoded({extended: true}));
      app.use(express.text())
      
      app.post("/api/getXML", (req, res) => {
          Request.post({
              "headers": { "content-type": "text/plain; charset=utf-8"},
              "url": "<url which return xml response>",
              "body": req.body
          }, (error, response, body) => {
              if(error) {
                  console.error(error);
                  res.send(error)
              }
              console.log("XML body :",body);
              res.send(body);
          });
      });
      

      这个想法来自链接https://www.thepolyglotdeveloper.com/2017/10/consume-remote-api-data-nodejs-application/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-12
        • 2012-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-17
        相关资源
        最近更新 更多