AJAX responseXML errors - javascript

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.

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,"<","<");
//text = replaceAll(text,">",">");
//text = replaceAll(text,""","\"");
//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.

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).

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?

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!");
}
}

To avoid your cross browser problems (and save yourself coding a lot of items that a strong community has already developed, tested, and reviewed), you should select a javascript library. JQuery and Dojo are great choices.

I believe that your web server need to serve correct response headers with 'ConferenceRoomSchedules.xml' e.g. Content-Type: text/xml or any other xml type.

The answer provided by Aron in https://stackoverflow.com/a/2081466/657416 is from my point of view the simplest (and the best) one. Here is my working code:
ajax = ajaxRequest();
ajax.overrideMimeType("text/xml");
ajax.open("GET", myurl;

Related

Getting A Cross-Origin XmlHttpRequest to Return an XML File in HTML5

EDIT: REMEMBER TO ALWAYS CHECK YOUR NETWORK TAB FOR ERRORS, MY POSTED ANSWER ELABORATES THAT THIS WAS A STUPID QUESTION ON MY PART, THANKS epascarello
I'm writing some backend code for an HTML5 website and I can't get this very important function to work. The site will often need to dynamically pull PHP-generated XML files from a different server. I'm pretty sure that server has Access-Control-Allow-Origin set to allow requests from this server. I will verify with my boss but he's out for a couple days and honestly it's more likely something I'm doing wrong. Does anyone see something wrong with this code?
Notice I have an alert at the bottom before request.send(null) and after. .send() works fine and the function completes if I request an XML file from the same server, but if I request from the other I get the "before" alert but not the "after". I am also seeing no errors or other alerts displayed to me.
Notes:
There are some references to global variables and such in other .js files. I've determined that including them would be pointless and just clutter the question.
'cross' is just a boolean for whether the request is cross origin, to another server.
function createXmlHttpRequestObject(cross) {
if(cross === undefined) {
cross = false;
}
var xmlHttp;
if(cross) {
if(window.XDomainRequest) {
try {
xmlHttp = new window.XDomainRequest();
} catch(e) {
xmlHttp = false;
}
} else {
xmlHttp = new XMLHttpRequest();
}
} else {
if(window.ActiveXObject) {
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
xmlHttp = false;
}
} else {
try {
xmlHttp = new XMLHttpRequest();
} catch(e) {
xmlHttp = false;
}
}
}
if(!xmlHttp) {
alert ("Error: CREATING XMLHTTP REQUEST OBJECT FAILED");
} else {
return xmlHttp;
}
}
//receives xml object from file
function getXmlObject(URL) {
//if url contains any of site root, then it is not cross domain
var cross = false;
if(!URL.includes(url_home)) {
cross = true;
}
var request = createXmlHttpRequestObject(cross);
var response;
if(window.ActiveXObject || window.XDomainRequest) {
request.onload = function(){
response = request.responseXML;
};
request.open('GET',URL,false);
request.send(null);
} else {
request.open('GET',URL,false);
request.onreadystatechange = function(){
if(request.readyState == 4) {
if(request.status == 200) {
response = request.responseXML;
} else {
var warn = 'NOT FOUND\n' + URL;
response = warn;
alert(warn);
}
}
};
alert("before");
request.send(null);
alert("after");
}
return response;
}
Found in the network tab confirmation that there is in fact no Access-Control-Allow-Origin flag on the server I'm trying to access. I'm gonna have to talk to the right people and see if that can change. Still, if this code can be improved or if there's still an issue here I'm not seeing please point it out.

Fall-back support for XMLHTTPRequest

We have a web application that makes use of native XMLHttpRequest() to send data back to our server. One of our larger clients have users that appear to be running IE8 in Win7 (64-bit) and have "Enable native XMLHTTP support" disabled in their browser.
We've implemented the typical scenario of instantiating an ActiveXObject in place of XMLHttpRequest in order to try to support the likes if IE6 (no native XMLHTTP support; yes, we still have clients running this on thin clients!) which I am hoping IE8 can utilise as a fallback if this checkbox option has been switched off. However, once an object has been created, I get a type error when calling open() method on it.
Here's my code:
// Posts back an xml file synchronously and checks for parse error.
// Returns xml object or null. Used in RSUserData.
XML.PostXmlFile = function(sURL, doc)
{
try
{
// Validate Input
if ((typeof (sURL) != "string") || (sURL == ""))
return null;
if (window.XMLHttpRequest) // IE7+, FF and Chrome
{
// Mozilla, create a new DOMParser and parse from string
// Although IE9 and IE10 can successfully load XML using this block, it can't use document.evaluate nor selectNodes/selectSingleNode to navigate it
// Ref: http://msdn.microsoft.com/en-us/library/ie/ms535874(v=vs.85).aspx
// Ref: http://msdn.microsoft.com/en-us/library/ie/ms534370(v=vs.85).aspx
// Ref: http://blogs.msdn.com/b/ie/archive/2012/07/19/xmlhttprequest-responsexml-in-ie10-release-preview.aspx
var req = new XMLHttpRequest();
req.open("post", sURL, false);
req.send(doc);
if (req.status != 200)
throw { message: 'HTTP Post returned status ' + req.status + ' (' + req.statusText + ') when sending to ' + sURL };
// IE11+: req.responseXML returns a native XML Document
// IE9/10: req.responseXML returns an IXMLDOMDocument2 object but we can convert req.responseText to native XML using DOMParser
// IE6/7/8: req.responseXML returns an IXMLDOMDocument2 object but DOMParser is not available
if (window.DOMParser)
{
var parser = new DOMParser();
return parser.parseFromString(req.responseText, 'application/xml');
}
else
return req.responseXML; // NATIVE
}
else
{
// up to IE6:
// Ref: http://blogs.msdn.com/b/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
var oXML = XML.GetActiveX_XML();
if (!oXML)
throw { message: "Could not instantiate an Msxml2 ActiveXObject", innerException: e };
oXML.open('POST', sURL, true);
oXML.send(sFile);
if (oXML.parseError.errorCode == 0)
{
xmlDoc = oXML;
return xmlDoc;
}
return null;
}
}
catch (e)
{
var s = "Exception in XML.PostXmlFile(). " + (e.message ? e.message : "");
throw { message: s, innerException: e };
}
}
XML.GetActiveX_XML = function()
{
var progIDs = ['Msxml2.DOMDocument.6.0', 'Msxml2.DOMDocument.3.0'];
for (var i = 0; i < progIDs.length; i++)
{
try
{
var oXML = new ActiveXObject(progIDs[i]);
var sl = oXML.getProperty("SelectionLanguage");
if (sl !== "XPath")
oXML.setProperty("SelectionLanguage", "XPath"); // Changes v3.0 from XSLPattern to XPath
var ns = "xmlns:rs='" + XML._nsResolver('rs') + "' xmlns:xsi='" + XML._nsResolver('xsi') + "'";
// ns = "xmlns:na='http://myserver.com' xmlns:nb='http://yourserver.com'";
oXML.setProperty("SelectionNamespaces", ns);
return oXML;
}
catch (ex) { }
}
return null;
}
NOTES:
The aim is to call to XML.PostXmlFile() with the url and payload.
Modern browsers use new XMLHttpRequest() as expected
IE6 is expected to use XML.GetActiveX_XML() on account that window.XMLHttpRequest returns falsey
IE8 with "Enable native XMLHTTP support" disabled falls through to the IE6 code (because window.XMLHttpRequest returns falsey) but the instantiated object fails because it doesn't support open() method (oXML.open('POST', sURL, true);)
Is there any way I can post my payload back using IE8 when "Enable native XMLHTTP support" is disabled?
You should see if the Microsoft.XMLHTTP is available before checking if there is a XMLHttpRequest:
var bActiveX;
try {
new ActiveXObject('Microsoft.XMLHTTP');
bActiveX = true;
}
catch(e) {
bActiveX = false;
}
And then, check in your if condition:
if (window.XMLHttpRequest || bActiveX) { // IE7+, FF and Chrome
var req = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
/* the rest of your code */
}

How do i link a xml file with several nodes and subnodes?

am looking for a javascript that will load an xml file and will display something like rectangules with links based on the xml child nodes, parents linked to childs and subnodes linked to nodes. how would i be able to do this?
You can accomplish this with AJAX.
First, create a function that will pull information from your XML file:
function loadXMLdoc(url) {
var ajaxRequest;
try {
// Opera 8.0+, Firefox, Safari
ajaxRequest = new XMLHttpRequest();
} catch(e) {
// Internet Explorer Browsers
try {
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
// Something went wrong
alert("Your browser broke!");
return false;
}
}
}
// Create a function that will receive data sent from the server
ajaxRequest.onreadystatechange = function() {
if (ajaxRequest.readyState === 4) {
if (ajaxRequest.status === 200) {
// a hidden div to display the result
var result = document.getElementById('result');
result.style.display = 'block';
result.innerHTML = ajaxRequest.responseText;
} else {
result.innerHTML = 'An error has occurred making the request';
}
}
ajaxRequest.open("GET", url, true);
ajaxRequest.send();
};
}
From here, you can start grabbing data from your XML file. Inside your if (ajaxRequest.status === 200) { } statement, you can start calling elements:
var elem = ajaxRequest.responseXML.getElementById('elem');
var parents = elem.parentNodes;
var children = parents.childNodes;
It's up to you exactly how you'd like to format this and what data you're grabbing, but this should be a good starting point for you.

How can I check existence of a file with JavaScript?

How can I check an existence of a file (It is an xml file that I would like to check in this case) with JavaScript?
if you're using jQuery, you can try to load the file
$.ajax({
type: "GET",
url: "/some.xml",
success: function()
{ /** found! **/},
error: function(xhr, status, error) {
if(xhr.status==404)
{ /** not found! **/}
}
});
if you're not using jQuery:
function ajaxRequest(){
var activexmodes=["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"]
//Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)
if (window.ActiveXObject){
for (var i=0; i<activexmodes.length; i++){
try{
return new ActiveXObject(activexmodes[i])
}
catch(e){
//suppress error
}
}
}
else if (window.XMLHttpRequest) // if Mozilla, Safari etc
return new XMLHttpRequest()
else
return false
}
var myrequest=new ajaxRequest()
myrequest.onreadystatechange=function(){
if (myrequest.readyState==4){ //if request has completed
if (myrequest.status==200 || window.location.href.indexOf("http")==-1){
// FOUND!
}
}
}
myrequest.open('GET', 'http://blabla.com/somefile.xml', true);
If the file is located on the same host that served the page containing the javascript you could try sending an ajax request and verify the returned status code:
function checkFile(fileUrl) {
var xmlHttpReq = false;
var self = this;
// Mozilla/Safari
if (window.XMLHttpRequest) {
self.xmlHttpReq = new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject) {
self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
self.xmlHttpReq.open('HEAD', fileUrl, true);
self.xmlHttpReq.onreadystatechange = function() {
if (self.xmlHttpReq.readyState == 4) {
if (self.xmlHttpReq.status == 200) {
alert('the file exists');
} else if (self.xmlHttpReq.status == 404) {
alert('the file does not exist');
}
}
}
self.xmlHttpReq.send();
}
checkFile('/somefile.xml');
Javascript doesn't really have any file handling functions. Your best bet is to do the check server side and send some context back to the client.
If you want to get super hacky you COULD call an xmlHttpRequest (If you're using jQuery take a look at the $.ajax function)
Once you call $.ajax you can use the success/error handlers to determine what to do. It should spit out an error if the file doesn't exist.
This of course is NOT a recommended way to do this.
I don't have enough reputation to post comments so let me note that in the Anwar Chandra's answer (non-jQuery version) you have to call eventually:
myrequest.send();
Also, the HEAD method would be better to "check existence of a file", because you don't need to read the whole file from the server.

How do I force or add the content length for ajax type POST requests in Firefox?

I'm trying to POST a http request using ajax, but getting a response from the apache server using modsec_audit that: "POST request must have a Content-Length header." I do not want to disable this in modsec_audit.
This occurs only in firefox, and not IE. Further, I switched to using a POST rather than a GET to keep IE from caching my results.
This is a simplified version of the code I'm using for the request, I'm not using any javascript framework.
function getMyStuff(){
var SearchString = '';
/* build search string */
...
/* now do request */
var xhr = createXMLHttpRequest();
var RequestString = 'someserverscript.cfm' + SearchString;
xhr.open("POST", RequestString, true);
xhr.onreadystatechange = function(){
processResponse(xhr);
}
xhr.send(null);
}
function processResponse(xhr){
var serverResponse = xhr.responseText;
var container = document.getElementById('myResultsContainer');
if (xhr.readyState == 4){
container.innerHTML = serverResponse;
}
}
function createXMLHttpRequest(){
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
try { return new XMLHttpRequest(); } catch(e) {}
return null;
}
How do I force or add the content length for ajax type POST requests in Firefox?
xhr.setRequestHeader("Content-Length", "0");
would be my best guess.
BTW, if you want to stop caching in IE, just add a random number onto the end, as in:
var RequestString = 'someserverscript.cfm' + SearchString + '&random=' + Math.random();
Try to actually send something instead of null (xhr.send(null);).

Categories

Resources