node.js 使用 xml2js 和 xmlbuilder 将 XML 解析为 JSON 并返回?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28688452/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 18:28:01  来源:igfitidea点击:

Parse XML to JSON and back ... with xml2js and xmlbuilder?

node.jsxml-parsingxml-builder

提问by prototype

Trying to parse XML into JSON with xml2jsand then return the JSON to XML using xmlbuilder(usually after modifying the content programmatically).

试图解析XML为JSON与xml2js,然后使用返回JSON来XML xmlbuilder(通常修改编程内容之后)。

I thinkthat the two should be complements, per this post https://github.com/oozcitak/xmlbuilder-js/issues/69. But am having some difficulty, and it's gotta be that I'm not getting the config parameters right.

认为这两者应该是互补的,根据这篇文章https://github.com/oozcitak/xmlbuilder-js/issues/69。但是我遇到了一些困难,一定是我没有正确设置配置参数。

Here's the code I'm running:

这是我正在运行的代码:

var xml = fs.readFileSync(__dirname + '/../xml/theme.xml', 'utf8');

xml2js.parseString(xml, { attrkey: '@',  xmlns: true }, function(err, json) {
    var xml2 = xmlbuilder.create(json,
       {version: '1.0', encoding: 'UTF-8', standalone: true}
    ).end({pretty: true, standalone: true})
});

Here's the first bit of the original XML:

这是原始 XML 的第一部分:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">
    <a:themeElements>
        <a:clrScheme name="Office">
            <a:dk1>
                <a:sysClr val="windowText" lastClr="000000"/>
            </a:dk1>
            <a:lt1>
                <a:sysClr val="window" lastClr="FFFFFF"/>
            </a:lt1>
            <a:dk2>
                <a:srgbClr val="1F497D"/>
            </a:dk2>
            ...
     </a:themeElements>           
 </a:theme>

Here;s how xml2js parses that to JSON, this looks right to me:

这里是 xml2js 如何将其解析为 JSON,这对我来说是正确的:

{
    "a:theme": {
        "@": {
            "xmlns:a": {
                "name": "xmlns:a",
                "value": "http://schemas.openxmlformats.org/drawingml/2006/main",
                "prefix": "xmlns",
                "local": "a",
                "uri": "http://www.w3.org/2000/xmlns/"
            },
            "name": {
                "name": "name",
                "value": "Office Theme",
                "prefix": "",
                "local": "name",
                "uri": ""
            }
        },
        "@ns": {
            "uri": "http://schemas.openxmlformats.org/drawingml/2006/main",
            "local": "theme"
        },
        "a:themeElements": [
            {
                "@ns": {
                    "uri": "http://schemas.openxmlformats.org/drawingml/2006/main",
                    "local": "themeElements"
                },
                "a:clrScheme": [
                    {
                        "@": {
                            "name": {
                                "name": "name",
                                "value": "Office",
                                "prefix": "",
                                "local": "name",
                                "uri": ""
                            }
                        },
                        "@ns": {
                            "uri": "http://schemas.openxmlformats.org/drawingml/2006/main",
                            "local": "clrScheme"
                        },
                       ...

Note that in the JSON above:

请注意,在上面的 JSON 中:

  1. the attribute (e.g. name=) are turned into keys inside an @object and
  2. the attribute values are turned into objects
  1. 属性(例如name=)被转换为@对象内的键,并且
  2. 属性值转化为对象

Now here's how it looks when xmlbuilder turns it back into XML:

现在这里是 xmlbuilder 将它转换回 XML 时的样子:

<a:theme ="[object Object]" ns="[object Object]">
  <a:themeElements ns="[object Object]">
    <a:clrScheme ="[object Object]" ns="[object Object]">
      <a:dk1 ns="[object Object]">
        <a:sysClr ="[object Object]" ns="[object Object]"/>
      </a:dk1>
      <a:lt1 ns="[object Object]">
        <a:sysClr ="[object Object]" ns="[object Object]"/>
      </a:lt1>
       ...
    </a:themeElements>
 </a:theme>

So there are two problems that XML builder is facing: * it's not recognizing the attribute names within the @object and * it's not recognizing the attribute value within the attribute object

因此,XML builder 面临两个问题: * 无法识别@对象中的属性名称; * 无法识别属性对象中的属性值

Hacking it appears that xmlbuilder wants attributes names structured like:

黑客似乎 xmlbuilder 想要结构化的属性名称,如:

  `{ "@name": "Office Theme"} `

rather than

而不是

  `{ "@" : { "name" : { value: "Office Theme" }}}`

Should I configure xml2js differently, xmlbuilder differently, or is there a different pair of libraries that can parse XML -> JSON -> XML?

我应该以不同的方式配置 xml2js,以不同的方式配置 xmlbuilder,还是有一对不同的库可以解析 XML -> JSON -> XML?

回答by Tomalak

The xml2js packagecomes with its own XML builder, to which the documentation has to say:

xml2js包本身自带的XML构建,到文档不得不说:

Since 0.4.0, objects can be also be used to build XML:

var fs = require('fs'),
    xml2js = require('xml2js');

var obj = {name: "Super", Surname: "Man", age: 23};
var builder = new xml2js.Builder();
var xml = builder.buildObject(obj);

At the moment, a one to one bi-directional conversion is guaranteed only for default configuration, except for attrkey, charkey and explicitArray options you can redefine to your taste.

从 0.4.0 开始,对象也可用于构建 XML:

var fs = require('fs'),
    xml2js = require('xml2js');

var obj = {name: "Super", Surname: "Man", age: 23};
var builder = new xml2js.Builder();
var xml = builder.buildObject(obj);

目前,只有默认配置才能保证一对一的双向转换,除了您可以根据自己的喜好重新定义的 attrkey、c​​harkey 和 explicitArray 选项。

So, after dropping your custom parser configuration, this works perfectly for me:

因此,在删除自定义解析器配置后,这对我来说非常有效:

var fs = require('fs');
var path = require('path');
var xml2js = require('xml2js');

xmlFileToJs('theme.xml', function (err, obj) {
    if (err) throw (err);
    jsToXmlFile('theme2.xml', obj, function (err) {
        if (err) console.log(err);
    })
});
// -----------------------------------------------------------------------

function xmlFileToJs(filename, cb) {
    var filepath = path.normalize(path.join(__dirname, filename));
    fs.readFile(filepath, 'utf8', function (err, xmlStr) {
        if (err) throw (err);
        xml2js.parseString(xmlStr, {}, cb);
    });    
}

function jsToXmlFile(filename, obj, cb) {
    var filepath = path.normalize(path.join(__dirname, filename));
    var builder = new xml2js.Builder();
    var xml = builder.buildObject(obj);
    fs.writeFile(filepath, xml, cb);
}

回答by Sumanth

While Converting XML to JSON , The xml2js maps the attributes to '$'. In case if your attributes key Name does not match with the Child Key Name . You could Merge the Attributes with Child elements . HEnce your JSON looks clean.

在将 XML 转换为 JSON 时,xml2js 将属性映射到“$”。如果您的属性键 Name 与 Child Key Name 不匹配。您可以将属性与子元素合并。因此您的 JSON 看起来很干净。

**

**

xml2js.Parser({ignoreAttrs : false, mergeAttrs : true})

xml2js.Parser({ignoreAttrs: false, mergeAttrs: true})

**

**

Might Solve your problem.

可能会解决您的问题。

回答by Parth Joshi

I came across similar requirement recently. Had to convert Yahoo weather service xml data into json object. Solved the issue with xml2js and js2xmlparser modules. Thought to share how I did here. An example which I worked out:

我最近遇到了类似的要求。必须将雅虎天气服务 xml 数据转换为 json 对象。解决了 xml2js 和 js2xmlparser 模块的问题。想分享我在这里的表现。我制定的一个例子:

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

https.get('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22surat%22)&format=xml&env=store%3A%2F%2F    datatables.org%2Falltableswithkeys', (resp) => {
    let data = '';

    // A chunk of data has been recieved.
    resp.on('data', (chunk) => {
        data += chunk;
    });

    // The whole response has been received. Print out the result.
    resp.on('end', () => {
        //console.log(JSON.parse(data).explanation);

        parseString(data, function (err, result) {
            console.log(JSON.stringify(result));
        });
    });

}).on("error", (err) => {
    console.log("Error: " + err.message);
});

After this one can use js2xmlparserfor converting the obtained json to xml.

之后就可以使用js2xmlparser将得到的json转换成xml了。

js2xmlparser.parse("weather", data); 
....

here's a Github link for the detailed code: https://github.com/joshiparthin/ReNode/tree/master/soap-api

这是详细代码的 Github 链接:https: //github.com/joshiparthin/ReNode/tree/master/soap-api