Importing Nodes in IE 6

With the prevalence of AJAX, the need to make dynamic changes to an XHTML tree within a browser becomes paramount. One of the main tasks behind the scenes is taking XML data from an AJAX response and updating the browser's DOM based upon the new information. If you send back XML in an XMLHTTPRequest, that should be straightforward: just use the DOM importNode() method.

In creating the AJAX-enabled Guise™ Internet application framework, I've found out that nothing is straightforward about AJAX, especially when it comes to Internet Explorer 6. Although the importNode() method has been recommended since 2000, six years later Microsoft still hasn't got around to implementing it, which means that the browser that most people use, IE6, can't even import new XML data in a standard way.

There have been naive attempts at providing alternatives to the importNode() method for IE6, but they ignore the extent to which IE6 (seemingly on purpose at times) goes to evade any sense of standards support or even consistency. IE Factor, for instance, claims you can simply create child elements recursively using createElement(). That's fine for a few safe cases. But Guise™ requires a general, consistent approach that will work for any arbitrary DOM tree.

Simply creating child elements with createElement() and then setting attributes will cause surprising problems in some instances. Try importing a <button> element; when you try to copy the type attribute, IE6 will croak. So you could decide instead to create a dummy element and use the Microsoft-created innerHTML to copy the serialized version of the node and then retrieve the new child node of the dummy element. Of course, because you can't use outerHTML on the returned text/xml XML tree from the XMLHTTPrequest response, you'll have to walk the returned tree and create your own serialization.

Manually serializing the data and using innerHTML produced more problems if you try to patch in a bare <th> or <td> cell of a table, because IE6 won't allow you to assign table cell data to a dummy <div> element—IE6 will attempt to create table elements. So you'll have to special-case <th> and <td> and place the serialized data inside <table><tbody><tr></tr></tbody></table>. And if you ever get an <option> element, you'll have to special-case it and put it inside a dummy <select></select>.

A replacement for importNode() on IE6 could be inserted into the BOM by checking for the existence of document.importNode(), allowing the rest of the code to use importNode() without caring if the browser actually supporte W3C standards or, like IE6, doesn't even follow its own standards most of the time. With a lot of experimentation, a robust replacement can be created—at least until the next esoteric combination of elements crop up and force new special cases to be added to the code.