JavaScript: Replacement for XMLSerializer.serializeToString()?
Asked Answered
S

4

12

I'm developing a website using the Seam framework and the RichFaces AJAX library (these isn't really all that important to the problem at hand - just some background).

I seem to have uncovered a bug, however, in RichFaces which, in certain instances, will cause AJAX-based updating to fail in IE8 (see here for more info: http://community.jboss.org/message/585737).

The following is the code where the exception is occurring:

   var anchor = oldnode.parentNode;

   if(!window.opera 
       && !A4J.AJAX.isWebkitBreakingAmps() 
       && oldnode.outerHTML 
       && !oldnode.tagName.match( /(tbody|thead|tfoot|tr|th|td)/i ) ) {
         LOG.debug("Replace content of node by outerHTML()");
         if (!Sarissa._SARISSA_IS_IE || oldnode.tagName.toLowerCase()!="table") {
         try {
           oldnode.innerHTML = "";
         } catch(e){    
           LOG.error("Error to clear node content by innerHTML "+e.message);
           Sarissa.clearChildNodes(oldnode);
         }
       }
           oldnode.outerHTML = new XMLSerializer().serializeToString(newnode);
   }

The last line (the one with XMLSerializer) is where the exception is occurring in IE. I was wondering if anyone knows of any replacement method / library / etc I could use there (only on IE is fine). Thanks.

EDIT: After doing some further research, it seems that the exception isn't being caused by XMLSerializer not being defined, rather it seems to happen when I try to assign the output from XMLSerializer to the outerHTML property of the oldnode.

This is strange because it works most times but fails in only a couple of scenarios (this piece of the framework seems to be rather important).

Can anyone think of any reason as to when the output from XMLSerializer (which, from the what the debugger shows, look to be quite valid HTML) is nonassignable to the outerHTML property of an element?

The strangest thing is, if I were to clone the element (using cloneNode(true)) and then set the outerHTML, it seems to work.

Shandy answered 6/2, 2011 at 21:38 Comment(1)
I've updated my answer following your edit.Mod
S
2

I've since discovered the reason (a while ago actually). It turns out that IE semi-validates (it'll balk at some errors but ignore others) inserted HTML. It was throwing some 'unknown error' or something similar which was pretty much completely useless since it gave no indication as to what went wrong - just that something went wrong.

In my case, it was because an <li /> was being inserted with a parent . If you're having similar issues, you may want to make sure you're not trying to be too clever with your HTML.

Shandy answered 17/2, 2011 at 21:14 Comment(0)
M
18

In IE you can simply use the xml property of the XML node, provided newnode really is an XML node rather than an HTML node:

function serializeXmlNode(xmlNode) {
    if (typeof window.XMLSerializer != "undefined") {
        return (new window.XMLSerializer()).serializeToString(xmlNode);
    } else if (typeof xmlNode.xml != "undefined") {
        return xmlNode.xml;
    }
    return "";
}

oldnode.outerHTML = serializeXmlNode(newnode);

Update following question update

I wouldn't use outerHTML to replace an element. It's not universally supported. Instead, you could use a mix of innerHTML and standard DOM methods as follows:

var tempEl = document.createElement("div");
tempEl.innerHTML = serializeXmlNode(newnode);
oldnode.parentNode.replaceChild(oldnode, tempEl.firstChild);
Mod answered 6/2, 2011 at 23:20 Comment(0)
S
2

I've since discovered the reason (a while ago actually). It turns out that IE semi-validates (it'll balk at some errors but ignore others) inserted HTML. It was throwing some 'unknown error' or something similar which was pretty much completely useless since it gave no indication as to what went wrong - just that something went wrong.

In my case, it was because an <li /> was being inserted with a parent . If you're having similar issues, you may want to make sure you're not trying to be too clever with your HTML.

Shandy answered 17/2, 2011 at 21:14 Comment(0)
Q
0

The suggested solution does not work for me. Here is my solution to this problem.

I replaced the line:

oldnode.outerHTML = new XMLSerializer().serializeToString(newnode);

by this:

if(navigator.appName.indexOf('Internet Explorer')>0){
    oldnode.outerHTML = newnode.xml
}else{
    oldnode.outerHTML = new XMLSerializer().serializeToString(newnode); 
}
Quarrier answered 8/9, 2011 at 13:9 Comment(1)
This is not a good way to detect. For example, IE9 added support for XMLSerializer. The upvoted answer will be more robust.Axletree
L
0

Edge case answer (mostly so I can find it later):

Sending HTML document as String to api to generate PDFs.

For anyone that needs to convert the document.body to a String and them submit it via a POST to a service to convert the document to a PDF - IE8 doesn't support XMLSerializer. That being said you can use: $(document.body).html(); for IE8.

/**
 * Decides the method by which to turn the document.body into a string that we can post to the PDF Api.
 * Most browsers support XMLSerializer, for others (ie8) use jquery's html method to generate a string.
 * @param xmldom - document.body
 * @return - string representation of the document body
 */
function serializeXml(xmldom){
    if (typeof XMLSerializer != "undefined"){
        return (new XMLSerializer()).serializeToString(xmldom);
    } else {
        return $(xmldom).html();
    }
}

Call it with: var dom = serializeXml(document.body);

Loutitia answered 24/10, 2012 at 22:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.