Leonidas-from-XIV / node-xml2js

XML to JavaScript object converter.
MIT License
4.84k stars 598 forks source link

#name Error: Invalid character in name #622

Open lengerrong opened 2 years ago

lengerrong commented 2 years ago

preserveChildrenOrder (default false): Modifies the behavior of explicitChildren so that the value of the "children" property becomes an ordered array. When this is true, every node will also get a #name field whose value will correspond to the XML nodeName, so that you may iterate the "children" array and still be able to determine node names. The named (and potentially unordered) properties are also retained in this configuration at the same level as the ordered "children" array. Added in 0.4.9.

when we parser xml string with {preserveChildrenOrder:true} option, each node will add a "#name" field. but when we try to builder the js object back to string again, we got Error:

Error: Invalid character in name at XMLStringifier.module.exports.XMLStringifier.assertLegalName (node_modules/xml2js/node_modules/xmlbuilder/lib/XMLStringifier.js:213:15)

reproduce code:

  let originXml = '<a:p><a:pPr marL="0" lvl="0" indent="0" algn="ctr" rtl="0"><a:spcBef><a:spcPts val="0"/></a:spcBef><a:spcAft><a:spcPts val="0"/></a:spcAft><a:buClr><a:schemeClr val="dk1"/></a:buClr><a:buSzPts val="1100"/><a:buFont typeface="Arial"/><a:buNone/></a:pPr><a:r><a:rPr lang="ja-JP" altLang="en-US"/><a:t>first line</a:t></a:r><a:br><a:rPr lang="en-CA" altLang="ja-JP" dirty="0"/></a:br><a:r><a:rPr lang="ja-JP" altLang="en-US"/><a:t>second line</a:t></a:r><a:endParaRPr lang="ja-JP" altLang="en-US" dirty="0"/></a:p>'
  new xml2js.Parser({explicitChildren: true, preserveChildrenOrder:true}).parseString(originXml, function(err, js) {
    console.log(js)
    let builder = new xml2js.Builder({ renderOpts: { pretty: false }, headless: true});
    let newxml = builder.buildObject(js);
    console.log(originXml)
    console.log(newxml)
    console.log(originXml === newxml)
  });
lengerrong commented 2 years ago

The parsed json object is like:

{
  'a:p': {
    '#name': 'a:p',
    '$$': [ [Object], [Object], [Object], [Object], [Object] ],
    'a:pPr': [ [Object] ],
    'a:r': [ [Object], [Object] ],
    'a:br': [ [Object] ],
    'a:endParaRPr': [ [Object] ]
  }
}

except '#name', '$$' will be consider as invalid TagName as well.

lengerrong commented 2 years ago

it seems like xml2js.Builder didn't support preserveChildrenOrder:true option yet.

ogomez92 commented 2 years ago

The author of the library specifies this in the docs: 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.

sad but true.

jainkuniya commented 1 year ago

HI, is there any work around for this?