oozcitak / xmlbuilder-js

An XML builder for node.js
MIT License
921 stars 110 forks source link

Using begin() causes methods to have side-effects #206

Closed danbars closed 5 years ago

danbars commented 5 years ago

I've found out the hard way that when I use begin instead of create, the xml object keeps an internal state that becomes updated when creating new nodes or traversing the tree. When using create those same methods just return new or existing nodes, but don't change any state.

E.g.

node = root;
node = node.element("somenode");
node.up();
node = node.element("othernode");

If root was created using begin I will get somenode andothernode as siblings. Whereas if root was created using create I will get othernode as child of somenode because node.up() has no effect.

This may be on purpose, but it is undocumented. I was trying to write code with visitor pattern, but it didn't work because I thought I'm passing a pointer to different nodes, while in fact it was the same node with internal state.

oozcitak commented 5 years ago

I'm sorry this caused you hardship. Your observation is correct. create returns a new node with each element call, while begin always returns an XMLDocumentCB object whose state is altered with each call. And it always returns the same instance.

My assumption was that if people built XML trees exactly as described in the docs, the difference would not matter. Your use case shows that I was wrong. 🤷‍♂️ I don't think I can fix this at this point. However, I will try to describe this better in the docs.

Also, I am currently working on the next generation of xmlbuilder at xmlbuilder2. It is in its early stages at the moment, but it is progressing quickly. Please feel free to drop by and comment. Maybe we can build a better API this time. 🤞

oozcitak commented 5 years ago

Added notes to the wiki:

https://github.com/oozcitak/xmlbuilder-js/wiki#begin-with-callback