I would like to extend the answer based on what is happening and provide a workaround. Running a GreaseMonkey script I tried to change the contents of an element, perhaps without changing it as such, but adding more elements, since the tag had only an IMG inside.
Original:
<a onclick=something><img src=url></a>
What I was trying to do was insert a DIV element that would already wrap the IMG and another new second SPAN child element, so the goal should have ended with the following:
<a onclick=something><div><img src=url><span>text</span></div></a>
Using the innerHTML property, it will look like this:
ANode.innerHTML = '<div>' + ANode.innerHTML + '<span>text</span></div>';
but instead I got:
<a onclick=something><div><a xmlns="http://www.w3.org/1999/xhtml"><img src=url><span>text</span></a></div></a>
Looking at the answers here helped a bit, although there is no real explanation. After some time, I noticed something that does not happen with an example in the question, which now, I believe, is the key to this problem. I was the same as jfrobishow, thinking where this is happening, I thought something was wrong concatenation of ANode.innerHTML.
When answering the original question, narrowing it down to where this happens, note that out-of-nowhere <A> included both IMG and new SPAN nodes, so I was curious that the unwanted <A> added just before how the div element was "built." So, from this example and my next workaround, you can notice that this happens when you insert a new BLOCK node inside the anchor, since both the DIV and P elements (the original example) are BLOCK elements.
(If you don't know what I mean by BLOCK, this is the display property of the http://www.w3schools.com/cssref/pr_class_display.asp element)
The obvious workaround is to replace the type of node you are inserting with a non-blocking element, in my case the problem was the DIV I wanted, but of course it depends on the purpose of your script, most of the things are by design, I put the DIV because I need it, so I fixed it by turning the DIV into another SPAN (which is an inline element), but I still need to behave like a block element, so style is what worked for me:
ANode.innerHTML = '<span style="display:block;">' + ANode.innerHTML + '<span>text</span></span>';
So, obviously, this problem is not from scripts (Javascript for me), but from style (CSS). By the way, this happened in Firefox 3.6.18, noting that this does not happen in Firefox 5.0.