Why should the node-wrappers keep the document alive?
for consistency, and convenience. In the same way you can get down from the document to the individual nodes you can get up: node.parent() and node.document() provide the means to walk up towards the document root.
node.begin_children() lets you iterate over all current child nodes, i.e. the nodes it returns will all be valid, thus this iterator interface is as stable as that of linked lists. I expect the same from node.parent() and node.document(), i.e. as long as there is an API to walk the tree, it should return valid objects.
That is not to say that these objects will remain valid over time. As you point out, erasing the content of a container will invalidate iterators you may still hold for that container.
Imagine a factory object that is initialized with a dom::node_ptr (holding configurational data, say). Whenever you access its method, the object looks up data in the node...
class factory { public: factory(dom::node_ptr n) : my_node(n) {} foo create_foo(); /* access my_node */ bar create_bar(); /* access my_node */ private: dom::node_ptr my_node; };
factory 'owns' the node, so whereever you instantiate the factory, you'd read in a dom::document, look up the relevant node, and pass that to the constructor:
factory *f; { dom::document_ptr document("config.xml"); dom::node_set set = document.root_node().find("//factory.info"); f = new factory(set[0]); } // document and set are now deleted, but factory still references // the document through its 'my_node' member
If the document wasn't ref-counted, you'd need to pass it along with the node to the factory, as only the factory would know when to drop it (in its destructor, presumably).
Here is the analogy I think works best...
container --> document container::value_type --> node container::iterator --> node_iterator container::pointer_type --> node_pointer container::reference_type --> node_reference
hmm, that makes it look simpler than it actually is: is there really a single 'value_type' ? Is there really a single iterator ? (iterating over all child nodes of a given parent and iterating over all attributes is not the same) Also, what is a node_reference (as opposed to a pointer) ?
Consider the following....
std::vector< foo > x; ... foo * y = &x[0]; x.erase( x.begin(), x.end() );
I don't expect y to add_ref x. I wouldn't mind if it did, but it wouldn't make y any more valid after the call to erase.
agreed. However, you explicitely erase elements, while all I want to prevent is implicit object destruction just because a reference to it
goes out of scope.
So the problem with add reffing the document is... what happens if the root node or some parent of a node you have a pointer to is erased from the document? libxml2 has no way of knowing you have a pointer to a child node.
that's right. And adding such a feature may be quite expensive memory / performance wise. As I said, I don't feel it's a problem, as you would
explicitely remove the node, so you should know what you are doing anyways. (As you said, you wouldn't even expect an iterator to be valid
after you erase the container's content).
Regards, Stefan
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost