AJAX responseXML errors

16,294

Solution 1

I was having the same problem a few years ago, then I gave up on responseXML and began always using responseText. This parsing function has always worked for me:

function parseXml(xmlText){
    try{
        var text = xmlText;
        //text = replaceAll(text,"&lt;","<");
        //text = replaceAll(text,"&gt;",">");
        //text = replaceAll(text,"&quot;","\"");
        //alert(text);
        //var myWin = window.open('','win','resize=yes,scrollbars=yes');
        //myWin.document.getElementsByTagName('body')[0].innerHTML = text;
        if (typeof DOMParser != "undefined") { 
            // Mozilla, Firefox, and related browsers 
            var parser=new DOMParser();
            var doc=parser.parseFromString(text,"text/xml");
            //alert(text);
            return doc; 
        }else if (typeof ActiveXObject != "undefined") { 
            // Internet Explorer. 
        var doc = new ActiveXObject("Microsoft.XMLDOM");  // Create an empty document 
            doc.loadXML(text);            // Parse text into it 
            return doc;                   // Return it 
        }else{ 
            // As a last resort, try loading the document from a data: URL 
            // This is supposed to work in Safari. Thanks to Manos Batsis and 
            // his Sarissa library (sarissa.sourceforge.net) for this technique. 
            var url = "data:text/xml;charset=utf-8," + encodeURIComponent(text); 
            var request = new XMLHttpRequest(); 
            request.open("GET", url, false); 
            request.send(null); 
            return request.responseXML; 
        }
    }catch(err){
        alert("There was a problem parsing the xml:\n" + err.message);
    }
}

With this XMLHttpRequest Object:

// The XMLHttpRequest class object

debug = false;

function Request (url,oFunction,type) {
    this.funct = "";
    // this.req = "";
    this.url = url;
    this.oFunction = oFunction;
    this.type = type;
    this.doXmlhttp = doXmlhttp;
    this.loadXMLDoc = loadXMLDoc;
}

function doXmlhttp() {
    //var funct = "";
    if (this.type == 'text') {
        this.funct = this.oFunction + '(req.responseText)';
    } else {
        this.funct = this.oFunction + '(req.responseXML)';
    }
    this.loadXMLDoc();
    return false;
}

function loadXMLDoc() {
    //alert(url);
    var functionA = this.funct;
    var req;
    req = false;

    function processReqChange() {
        // alert('reqChange is being called');
        // only if req shows "loaded"
        if (req.readyState == 4) {
            // only if "OK"
            if (req.status == 200) {
                // ...processing statements go here...
                eval(functionA);
                if(debug){
                    var debugWin = window.open('','aWindow','width=600,height=600,scrollbars=yes');
                    debugWin.document.body.innerHTML = req.responseText;
                }
            } else {
                alert("There was a problem retrieving the data:\n" +
                    req.statusText + '\nstatus: ' + req.status);
                if(debug){
                    var debugWin = window.open('','aWindow','width=600,height=600,scrollbars=yes');
                    debugWin.document.body.innerHTML = req.responseText;
                }
            }
            }
    }

    // branch for native XMLHttpRequest object
    if(window.XMLHttpRequest) {
        try {
            req = new XMLHttpRequest();
        } catch(e) {
            req = false;
        }
    // branch for IE/Windows ActiveX version
    } else if(window.ActiveXObject) {
        try {
                req = new ActiveXObject("Msxml2.XMLHTTP");
        } catch(e) {
                try {
                    req = new ActiveXObject("Microsoft.XMLHTTP");
                } catch(e) {
                    req = false;
                }
        }
    }



    if(req) {
        req.onreadystatechange = processReqChange;
        if(this.url.length > 2000){
            var urlSpl = this.url.split('?');
            req.open("POST",urlSpl[0],true);
            req.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
            req.send(urlSpl[1]);
        } else {
            req.open("GET", this.url, true);
            req.send("");
        }
    }
}

function browserSniffer(){
    if(navigator.userAgent.toLowerCase().indexOf("msie") != -1){
        if(navigator.userAgent.toLowerCase().indexOf("6")){
            return 8;
        }else{
            return 1;
        }
    }
    if(navigator.userAgent.toLowerCase().indexOf("firefox") != -1){
        return 2;
    }
    if(navigator.userAgent.toLowerCase().indexOf("opera") != -1){
        return 3;
    }
    if(navigator.userAgent.toLowerCase().indexOf("safari") != -1){
        return 4;
    }
    return 5;
}

Granted, this is very old code, but it is still working for me on a site I built a few years ago. I agree with everyone else though I typically use a framework nowadays so I don't have to use this code or anything like it anymore.

You can ignore some of the particulars with the split, etc... in the Request onreadystate function. It was supposed to convert the request to a post if it was longer than a certain length, but I just decided it was always better to do a post.

Solution 2

This problem occurs mostly when content type is mis-detected by the browser or it's not sent correctly.

Its easier to just override it:

var request = new XMLHttpRequest(); 
request.open("GET", url, false); 
request.overrideMimeType("text/xml");
request.send(null); 
return request.responseXML; 

Not sure why... This problem occurs only with Safari and Chrome (WebKit browsers, the server sends the headers correctly).

Solution 3

What I can suggest you is to take a look at frameworks that hide and manage these cross-browser issues for you (in a reliable way). A good point here is jQuery. Doing these things yourself can become quite difficult and complex.

This may be what you need.

//Edit: This is how the w3school shows it:

function ajaxFunction()
{
var xmlhttp;
if (window.XMLHttpRequest)
  {
  // code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else if (window.ActiveXObject)
  {
  // code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
else
  {
  alert("Your browser does not support XMLHTTP!");
  }
}

Solution 4

Are you calling the URL relative to the current document? Since IE would be using the ActiveXObject, it might need an absolute path, for example:

http://some.url/ConferenceRoomSchedules.xml

As for the XML, are you sure it's well-formed? Does it load in an XML editor, for instance?

Share:
16,294
Tony L.
Author by

Tony L.

I am a programmer always sharping my knowledge. I like to play soccer and ultimate frisbee, watch movies, read books, hang out with friends, and surf the net.

Updated on June 08, 2022

Comments

  • Tony L.
    Tony L. almost 2 years

    I've been having some weird issues when it comes to make an AJAX request and handling the response.

    I am making an ajax call for an xml file. however when i get the response the xhr.responseText property works fine in firefox but not in IE. Another thing is that I am trying to access the xhr.responseXML as XMLDocument, but it tells me in firefox it tells me that xhr.responseXML is undefined in ie it doesnt even show me the undefined error or displays the output.

    This is the code I am using to make the request:

    var ajaxReq = function(url, callback) {
        //initialize the xhr object and settings
        var xhr = window.ActiveXObject ?
                new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(),
        //set the successful connection function
            httpSuccess = function(xhr) {
                try {
                    // IE error sometimes returns 1223 when it should be 204
                    //  so treat it as success, see XMLHTTPRequest #1450
                    // this code is taken from the jQuery library with some modification.
                    return !xhr.status && xhr.status == 0 ||
                            (xhr.status >= 200 && xhr.status < 300) ||
                            xhr.status == 304 || xhr.status == 1223;
                } catch (e) { }
                return false;
            };
    
        //making sure the request is created
        if (!xhr) {
            return 404; // Not Found
        }
    
    
        //setting the function that is going to be called after the request is made
        xhr.onreadystatechange = function() {
            if (!httpSuccess(xhr)) {
                return 503; //Service Unavailable
            }
            if (xhr.responseXML != null && xhr.responseText != null &&
                    xhr.responseXML != undefined && xhr.responseText != undefined) {
                callback(xhr);
            }
        };
    
    
        //open request call
        xhr.open('GET', url, true);
    
        //setup the headers
        try {
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            xhr.setRequestHeader("Accept", "text/xml, application/xml, text/plain");
        } catch ( ex ) {
            window.alert('error' + ex.toString());
        }
    
        //send the request
        try {
            xhr.send('');
        } catch (e) {
            return 400; //bad request
        }
    
        return xhr;
    };
    

    and this is how i am calling the function to test for results:

    window.onload = function() {
        ajaxReq('ConferenceRoomSchedules.xml', function(xhr) {
            //in firefox this line works fine,
            //but in ie it doesnt not even showing an error
            window.document.getElementById('schedule').innerHTML = xhr.responseText;
            //firefox says ''xhr.responseXML is undefined'.
            //and ie doesn't even show error or even alerts it.
            window.alert(xhr.reponseXML.documentElement.nodeName);
        });
    }
    

    This is also my first attempt to work with AJAX so there might be something that I am not looking at right. I've been searching crazy for any indications of why or how to fix it, but no luck there. any ideas would be great.

    EDIT:

    I know this would be better with a framework, but the boss doesn't want to add a framework for just an ajax functionality ('just' is not a fair word for ajax :P). So I am doing it with pure javascript.

    The XML file is well-formed, I see it well in the web browser, but for completion this is the testing file I am using:

    <?xml version="1.0" encoding="utf-8"?>
    <rooms>
      <room id="Blue_Room">
        <administrator>somebody@department</administrator>
        <schedule>
          <event>
            <requester>
              <name>Johnny Bravo</name>
              <email>jbravo@department</email>
            </requester>
            <date>2009/09/03</date>
            <start_time>11:00:00 GMT-0600</start_time>
            <end_time>12:00:00 GMT-0600</end_time>
          </event>
        </schedule>
      </room>
      <room id="Red_Room">
        <administrator>somebody@department</administrator>
        <schedule>
        </schedule>
      </room>
      <room id="Yellow_Room">
        <administrator>somebody@department</administrator>
        <schedule>
        </schedule>
      </room>
    </rooms>
    

    EDIT 2: Well the good news is that I convinced my boss to use jQuery, the bad news is that AJAX still perplexes me. I'll read more about it just for curiousity. Thanks for the tips and I gave the answer credit to Heat Miser because he was the closest working tip.

  • Spike Williams
    Spike Williams almost 15 years
    This is a good suggestion. Let the library worry about the cross browser issues.
  • Tony L.
    Tony L. almost 15 years
    I agree, I've used jQuery but my boss doesn't want to fill up the website with a whole framework if we are just going to use ajax. So I have to do it myself. Although I am still trying to convince him to use a framework.
  • Tony L.
    Tony L. almost 15 years
    Thanks for the reply. I tried using absolute path but still no luck, same results in IE.
  • user5880801
    user5880801 almost 15 years
    @Tony L., tell him jQuery is a script, not a framework. Framework sounds heavy.
  • abhijeet nigoskar
    abhijeet nigoskar almost 15 years
    @Tony: and then tell him that by writing it yourself, you need about 5 days developing time + probably bug-fixing due to some strange browser quirks and with jQuery you get everything for free and a lot safer. Take a look at this here: code.google.com/apis/ajaxlibs
  • Tony L.
    Tony L. almost 15 years
    responseText looks solid in a cross-browser environment I think I am going to use this method then. Thanks for the script
  • Heat Miser
    Heat Miser almost 15 years
    No problem, glad I could help!
  • Admin
    Admin over 7 years
    Your answer pointed me in the right direction for a similar problem 7 years later :) I was using .response in IE9 and that didn't work while working in all other browsers. .responseText works in all browsers. Good!