innerHTML in XHTML pages

Handling of innerHTML in XHTML pages (with MIME type application/xhtml+xml) is weird. Getting works, setting doesn't.

Test page. Workaround is not included.
Reported by ppk.

Mozilla, Safari | Reported on 2 November 2004.

This site is no longer maintained. I’m sorry, but it’s just too much work for too little return. You can continue to browse old bug reports, though.

Search reports by browser:

Atom RSS


(Add your own)

1 Posted by Geoff Stearns on 24 November 2004 | Permalink

I believe this isn't a bug, it was disabled on purpose.

XHTML documents served as application/xhtml+xml are XML documents, so they have to be well formed in order for the browser to render them. if you could just insert any string in to your document then you introduce the possibility that you'll get a malformed document. so the browser, in order to use innerHTML would have to parse the string as xml, and then append it to the document.

the workaround for this problem is to use createElement() and createElementNS() and node.appendChild() to build your new XHTML and insert it into your document.

2 Posted by Aankhen on 24 November 2004 | Permalink

It makes sense to me... getting the innerHTML of an element doesn't affect the page, so there's no harm in supporting it, whereas setting it does affect the page, as explained by Geoff.

I agree that it might be confusing though. :-)

3 Posted by ppk on 25 November 2004 | Permalink

Yes, that makes sense. However, I'd have preferred the browsers to entirely remove innerHTML instead of supporting only half of it.

4 Posted by hemebond on 14 December 2004 | Permalink

Argh! This is annoying. If setting the innerHTML invalidates the document, then fail; otherwise I should be able to set it. Is there an easy way to recreate this functionality using the DOM?

5 Posted by Christian Fecteau on 22 December 2004 | Permalink

I've come across this bug a few months ago and decided at this time to use the same workaround as Geoff. I didn't try to understand why innerHTML was not working anymore with this Content-Type, and I didn't consider it as a bug as well. I also came to the conclusion that it was disabled on purpose, and now as I read it, Goeff's explanation makes perfect sense to me.

6 Posted by Thomas McGee on 23 January 2005 | Permalink

Not sure that this is the right explanation. If you do the setting, it doesn't get drawn to the screen, but if you alert out the innerHTML of the element that you changed, you get what you set it to.

alert(theObject.innerHTML); // alerts the old stuff
theObject.innerHTML = "some text";
alert(theObject.innerHTML); // alerts "some text"

7 Posted by Unknown W. Brackets on 14 April 2005 | Permalink

David "liorean" Andersson was quoted, on the test page, as saying:

Have you tried either using a Range and the [object Range].createContextualFragment function or the global DOMParser function directly to see if they too fail this way?

This means using the following code to replicate innerHTML:

var range = document.createRange();

Or similar. This throws an error, just like innerHMTL - because this is how innerHTML works. Using a DOMParser works better, but still not perfectly:

var nodes = new DOMParser().parseFromString(value, 'text/xml');

var range = document.createRange();

for (var i = 0; i < nodes.childNodes.length; i++)

The problem here is that the elements are not created with the right namespaceURI.

I experienced odd behavior when I tried adding a temporary element around the value and adding an xmlns to it. It seemed as if not all children got the namespaceURI set properly.


8 Posted by Anne on 20 May 2005 | Permalink

9 Posted by Jamie on 16 April 2006 | Permalink

In Firefox (Gecko 1.8), this is fixed. Both the get and the set work correctly on the test page.

10 Posted by Carlos on 8 June 2007 | Permalink

I have also found getting innerHTML in XHTML to be flawed as it strips the closing '/' from image,br and other tags that require it.

11 Posted by Henri on 22 April 2008 | Permalink

It's better to use appendChild. This works fine. But, for the small things it's easy to use innerHTML :)