The Mystery of Removing XML DOM Nodes | January 16th, 2008
I was reviewing some code today and came across something that seemed very strange. There is a method we use for removing all the child nodes of a parent node in an XML document and it looked like this:
nitobi.xml.removeChildren = function(parentNode)
{
var children = nitobi.xml.getChildNodes(parentNode); // gets children that are not empty text nodes
for (var i = 0, len = children.length; i < len; i++)
{
parentNode.removeChild(children[i]);
}
}
Someone (probably me) was trying to save processing and store the child node collection length rather than re-calculate it every time through the loop. Seems good but one will notice that we are removing the child at the i'th index and so half way though deleting the child nodes we are going to try and delete the len/2+1 node but there will only be len/2 nodes in the collection (or something along those lines).
So I "fixed" it and made it look like this:
nitobi.xml.removeChildren = function(parentNode)
{
var children = nitobi.xml.getChildNodes(parentNode);
for (var i = 0, len = children.length; i < len; i++)
{
parentNode.removeChild(children[0]);
}
}
Now it would always remove the first element in the collection and iterate over the original collection length - done and done. Oh wait but no. So I go to test this in Firefox and low and behold it crashes like AAPL after MacWorld.
Then I finally get my act together and test both approaches in Internet Explorer and the latter approach - the expected solution - is the one that works. So Firefox is doing some strange things with the length of the child node collection.
January 16th, 2008 at 8:27 pm
Crashes like AAPL — hehehe, nice.
January 16th, 2008 at 10:02 pm
btw: a really elegant solution that was shown to me was:
while(element.firstChild)
element.removeChild( element.firstChild );
I love it for its simplicity.
January 17th, 2008 at 4:56 pm
hehe - in fact that’s what I decided on in the end Jonathan