Leonidas-from-XIV / node-xml2js

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

Allow the option mergeAttrs in the Builder #606

Open franciscohanna92 opened 3 years ago

franciscohanna92 commented 3 years ago

My proposal is to support the mergeAttrs in the Builder. This would allow us to avoid having to specify the attributes in the $ property for an object. Basically, it would be the inverse operation for the one already present in the parser with mergeAttrs: true.

An example would be:

const xmlObject = {
  element: {
    someAttribute: "lorem",
    anotherAttribute: "ipsum",
    _: "Text content",
  },
};

const xmlBuilder = new xml2js.Builder({ mergeAttrs: true });
const xmlString = xmlBuilder.buildObject(xmlObject)

The resulting xmlString would be:

<?xml version="1.0" encoding="UTF-8"?>
<element someAttribute="lorem" anotherAttribute="ipsum">
  Text content
</element>

I'm not familiar with the codebase. Is this possible to implement?

jasonperrone commented 1 year ago

@franciscohanna92 I love this idea and I respect the motivation for it. Something that is absolutely driving me nuts about xml2js is when you have an object with one or more arrays in it that are converted to child tags. Each of those arrays contains objects that will be turned into XML elements. I can see no straightforward way whatsoever to tell xml2js which properties in those objects I want to be attributes, not elements. It seems I have to go into every single object of every single array and manually set the properties that I want to be attributes into the $: key and then delete the original property so that it doesn't become an XML element. It is absolute torture. Is that what motivated you to request this change? If so, did you ever find a more elegant way to tell either Parser or Builder "hey, I want these properties on the objects in my arrays to be attributes, not elements"?

jasonperrone commented 1 year ago

Meanwhile, I saw this in xmlbuilder:

var builder = require('xmlbuilder');

var obj = {
  root: {
    xmlbuilder: {
      repo: {
        '@type': 'git', // attributes start with @
        '#text': 'git://github.com/oozcitak/xmlbuilder-js.git' // text node
      }
    }
  }
};

var xml = builder.create(obj).end({ pretty: true});
console.log(xml);

"Attributes start with @". That would sure be nice.

Maybe I should be using xmlbuilder directly instead of xml2js...

jasonperrone commented 1 year ago

Yes, switching to xmlbuilder was the answer for me.