【问题标题】:Reading XML file in Node.js在 Node.js 中读取 XML 文件
【发布时间】:2015-12-28 15:40:18
【问题描述】:

我正在学习如何使用 Node.js。此时,我有一个如下所示的 XML 文件:

sitemap.xml

<?xml version="1.0" encoding="utf-8"?>

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
  <url>
    <loc>http://www.example.com</loc>
    <lastmod>2015-10-01</lastmod>
    <changefreq>monthly</changefreq>
  </url>

  <url>
    <loc>http://www.example.com/about</loc>
    <lastmod>2015-10-01</lastmod>
    <changefreq>never</changefreq>
  </url>

  <url>
    <loc>http://www.example.com/articles/tips-and-tricks</loc>
    <lastmod>2015-10-01</lastmod>
    <changefreq>never</changefreq>
    <article:title>Tips and Tricks</blog:title>
    <article:description>Learn some of the tips-and-tricks of the trade</article:description>
  </url>
</urlset>

我正在尝试在我的 Node 应用程序中加载此 XML。加载时,我只想获取包含使用 &lt;article: 元素的 url 元素。在这个时候,我被困住了。现在,我通过以下方式使用XML2JS

var parser = new xml2js.Parser();
fs.readFile(__dirname + '/../public/sitemap.xml', function(err, data) {
    if (!err) {
        console.log(JSON.stringify(data));
    }
});

console.log 语句执行时,我只是在控制台窗口中看到一堆数字。像这样的:

{"type":"Buffer","data":[60,63,120, ...]}

我错过了什么?

【问题讨论】:

  • 还有什么理由将其转换为 JSON?使用 XMLDOM,XPAth 用于节点,因为您知道它是 XML 并且可以使用 XPath 将是另一个需要考虑的途径。

标签: javascript xml node.js


【解决方案1】:

使用 xml2json

https://www.npmjs.com/package/xml2json

fs = require('fs');
var parser = require('xml2json');

fs.readFile( './data.xml', function(err, data) {
    var json = parser.toJson(data);
    console.log("to json ->", json);
 });

【讨论】:

  • 对所有研究 XML 到 JSON 转换的人的小提醒:xml2json 库对我来说确实比 xml2js 工作得更好。
  • 另一个库如xml-js 能够双向转换。这不是你需要这个的时候。因为 javascript 中的内部表示在此类库中始终是特定的。 (xml -> javascript -> 正确的 json)
  • 值得注意的是parse.toJson(data)返回一个JSON字符串。如果您想以 Javascript 对象的形式访问parse.toJson(data) 的结果,您需要通过调用JSON.parse 再采取一步。 const json = JSON.parse(parser.toJson(data)); 给你一个原始对象,所以你可以做console.log(json.myPropertyKey)
【解决方案2】:

来自the documentation

回调传递了两个参数(err, data),其中 data 是 文件的内容。

如果未指定编码,则返回原始缓冲区。

如果 options 是一个字符串,那么它指定编码。示例:

fs.readFile('/etc/passwd', 'utf8', callback);

你没有指定编码,所以你得到的是原始缓冲区。

【讨论】:

    【解决方案3】:

    @Sandburg 在评论中提到了xml-js,它对我来说效果最好(问这个问题几年后)。我尝试的其他方法是:xml2json 需要一些我不想处理的 Windows Sdk,xml2js 没有提供足够简单的 OTB 方法来搜索属性。

    我不得不在 3 个节点深的 xml 文件中提取特定属性,xml-js 轻松做到了。

    https://www.npmjs.com/package/xml-js

    使用以下示例文件stats.xml

    <stats>
      <runs>
        <latest date="2019-12-12" success="100" fail="2" />
        <latest date="2019-12-11" success="99" fail="3" />
        <latest date="2019-12-10" success="102" fail="0" />
        <latest date="2019-12-09" success="102" fail="0" />
      </runs>
    </stats>
    

    我使用xml-js 来查找具有@date='2019-12-12' 属性的元素/stats/runs/latest,就像这样

    const convert = require('xml-js');
    const fs = require('fs');
    
    // read file
    const xmlFile = fs.readFileSync('stats.xml', 'utf8');
    
    // parse xml file as a json object
    const jsonData = JSON.parse(convert.xml2json(xmlFile, {compact: true, spaces: 2}));
    
    const targetNode = 
    
        // element '/stats/runs/latest'
        jsonData.stats.runs.latest
    
        .find(x => 
    
            // attribute '@date'
            x._attributes.date === '2019-12-12'
        );
    
    // targetNode has the 'latest' node we want
    // now output the 'fail' attribute from that node
    console.log(targetNode._attributes.fail);  // outputs: 2
    

    【讨论】:

      【解决方案4】:

      fs.readFile 有一个可选的第二个参数:编码。如果你不包含这个参数,它会自动返回一个 Buffer 对象。

      https://nodejs.org/api/fs.html#fs_fs_readfile_filename_options_callback

      如果您知道编码,请使用:

      fs.readFile(__dirname + '/../public/sitemap.xml', 'utf8', function(err, data) {
          if (!err) {
              console.log(data);
          }
      });
      

      【讨论】:

      • 您的 parser 变量从未使用过?
      • 解析器变量来自原始问题,我不知道如何从他们的代码中使用它。已删除。
      • 我花了一些时间尝试将 xml 转换为字符串,但这是更好的选择。或者使用readFileSync()
      【解决方案5】:

      步骤 1 npm install xml2js --save

      const xml2js = require('xml2js');
      const fs = require('fs');
      const parser = new xml2js.Parser({ attrkey: "ATTR" });
      
      // this example reads the file synchronously
      // you can read it asynchronously also
      let xml_string = fs.readFileSync("data.xml", "utf8");
      
       parser.parseString(xml_string, function(error, result) {
         if(error === null) {
            console.log(result);
        }
        else {
          console.log(error);
        }
      

      });

      【讨论】:

        【解决方案6】:

        你可以试试这个

        npm install express-xml-bodyparser --save
        

        在客户端:-

         $scope.getResp = function(){
             var posting = $http({
                   method: 'POST',
                   dataType: 'XML',
                   url: '/getResp/'+$scope.user.BindData,//other bind variable
                   data: $scope.project.XmlData,//xmlData passed by user
                   headers: {
                      "Content-Type" :'application/xml'
                    },
                   processData: true
                   });
               posting.success(function(response){
               $scope.resp1 =  response;
               });
           };
        

        在服务器端:-

        xmlparser = require('express-xml-bodyparser');
        app.use(xmlparser());
        app.post('/getResp/:BindData', function(req, res,next){
          var tid=req.params.BindData;
          var reqs=req.rawBody;
          console.log('Your XML '+reqs);
        });
        

        【讨论】:

          【解决方案7】:

          对于快递服务器:

            app.get('/api/rss/', (_request: Request, response: Response) => {
              const rssFile = fs.readFileSync(__dirname + '/rssFeeds/guardian.xml', { encoding: 'utf8' })
          
              console.log('FILE', rssFile)
          
              response.set('Content-Type', 'text/xml')
              response.send(rssFile)
            })
          
          • 接受请求
          • 读取文件
          • 设置xml标头
          • 返回文件

          【讨论】:

            【解决方案8】:

            您还可以在解析之前使用正则表达式来删除与您的条件不匹配的元素:

            var parser = new xml2js.Parser();
            fs.readFile(__dirname + '/../public/sitemap.xml', "utf8",function(err, data) {
                // handle err...
            
                var re = new RegExp("<url>(?:(?!<article)[\\s\\S])*</url>", "gmi")
                data = data.replace(re, ""); // remove node not containing article node
                console.log(data);
                //... parse data ...
            
            
            
            });
            

            例子:

               var str = "<data><url><hello>abc</hello><moto>abc</moto></url><url><hello>bcd</hello></url><url><hello>efd</hello><moto>poi</moto></url></data>";
               var re = new RegExp("<url>(?:(?!<moto>)[\\s\\S])*</url>", "gmi")
               str = str.replace(re, "")
            
               // "<data><url><hello>abc</hello><moto>abc</moto></url><url><hello>efd</hello><moto>poi</moto></url></data>"
            

            【讨论】:

              【解决方案9】:

              为了read an XML file in Node,我喜欢XML2JS package。这个包让我可以轻松地在 JavaScript 中使用 XML。

              var parser = new xml2js.Parser();       
              parser.parseString(fileData.substring(0, fileData.length), function (err, result) {
                var json = JSON.stringify(result);
              });
              

              【讨论】:

              • 这个模块太有限了...不能事件处理嵌套节点,并且无论顺序如何都返回数组中具有相同标签的节点... WTF?
              【解决方案10】:

              来晚了,只是在这里添加一个简单的提示, 如果你打算在js中使用解析后的数据或者保存为json文件,请务必将explicitArray设置为false。输出会更加 js 友好

              所以它看起来像,
              letparser=newxml2js.Parser({explicitArray:false})

              参考: https://github.com/Leonidas-from-XIV/node-xml2js

              【讨论】:

                猜你喜欢
                • 2018-05-08
                • 1970-01-01
                • 2013-08-25
                • 2021-11-29
                • 1970-01-01
                • 2011-11-05
                • 1970-01-01
                • 2015-11-06
                • 2011-11-23
                相关资源
                最近更新 更多