mardi 24 février 2015

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

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


I think that the two should be complements, per this post http://ift.tt/1vu6Rol. But am having some difficulty, and it's gotta be that I'm not getting the config parameters right.


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 version="1.0" encoding="UTF-8" standalone="yes"?>
<a:theme xmlns:a="http://ift.tt/1dB6t9q" 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:



{
"a:theme": {
"@": {
"xmlns:a": {
"name": "xmlns:a",
"value": "http://ift.tt/1dB6t9q",
"prefix": "xmlns",
"local": "a",
"uri": "http://ift.tt/1lvhzme"
},
"name": {
"name": "name",
"value": "Office Theme",
"prefix": "",
"local": "name",
"uri": ""
}
},
"@ns": {
"uri": "http://ift.tt/1dB6t9q",
"local": "theme"
},
"a:themeElements": [
{
"@ns": {
"uri": "http://ift.tt/1dB6t9q",
"local": "themeElements"
},
"a:clrScheme": [
{
"@": {
"name": {
"name": "name",
"value": "Office",
"prefix": "",
"local": "name",
"uri": ""
}
},
"@ns": {
"uri": "http://ift.tt/1dB6t9q",
"local": "clrScheme"
},
...


Note that in the JSON above:



  1. the attribute (e.g. name=) are turned into keys inside an @ object and

  2. the attribute values are turned into objects


Now here's how it looks when xmlbuilder turns it back into 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


Hacking it appears that xmlbuilder wants attributes names structured like:



`{ "@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?


Aucun commentaire:

Enregistrer un commentaire