web-dev-qa-db-ja.com

XMLをJSONに解析して元に戻します... xml2jsとxmlbuilderを使用しますか?

xml2js を使用してXMLをJSONに解析し、 xmlbuilder を使用してJSONをXMLに戻そうとしています(通常はプログラムでコンテンツを変更した後)。

thinkこの投稿によると、2つは補完する必要があります https://github.com/oozcitak/xmlbuilder-js/issues/ 69 。しかし、いくつかの問題が発生しており、構成パラメーターが正しく取得されていない可能性があります。

これが私が実行しているコードです:

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

元の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>

これが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"
                        },
                       ...

上記のJSONでは次のことに注意してください。

  1. 属性(例:name=)は、@オブジェクト内のキーに変換されます。
  2. 属性値はオブジェクトに変換されます

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>

したがって、XMLビルダーが直面している2つの問題があります。* @オブジェクト内の属性名を認識しないことと*属性オブジェクト内の属性値を認識しないことです。

ハッキングすると、xmlbuilderは次のような構造の属性名を必要としているようです。

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

のではなく

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

Xml2jsを別の方法で構成する必要がありますか、xmlbuilderを別の方法で構成する必要がありますか、それともXML-> JSON-> XMLを解析できる別のライブラリのペアがありますか?

7
prototype

xml2jsパッケージ には独自のXMLビルダーが付属しており、ドキュメントには次のように記載されています。

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

現時点では、1対1の双方向変換は、好みに合わせて再定義できるattrkey、c​​harkey、explicitArrayオプションを除いて、デフォルト構成でのみ保証されています。

したがって、カスタムパーサー構成を削除した後、これは私にとって完全に機能します。

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

最近、同様の要件に遭遇しました。 Yahooウェザーサービスの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);
});

この後、取得したjsonをxmlに変換するために js2xmlparser を使用できます。

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

詳細なコードのGithubリンクは次のとおりです。 https://github.com/joshiparthin/ReNode/tree/master/soap-api

1
Parth Joshi

XMLをJSONに変換する際、xml2jsは属性を「$」に​​マップします。属性キー名が子キー名と一致しない場合。属性を子要素とマージできます。 JSONがきれいに見えるので。

****

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

****

あなたの問題を解決するかもしれません。

1
Sumanth