I'm a newbie trying to modify the code in an AJAX tutorial to load data from an XML file, and it is not working. The code is in a php file that is invoked with the URL: getXMLTest.php?showName=photoShowTest.xml The code I've written (mostly copied from the tutorial, actually) is:

<!Doctype HTML>
<html>

<head>
  <script language="javascript" type="text/javascript">
  
    var XMLDoc;
  
  
    function getXMLDoc(XMLFile){
      XMLDocRequest=false;  // The variable that makes Ajax possible!
  	
      try{	
  		// Opera 8.0+, Firefox, Safari
        XMLDocRequest = new XMLHttpRequest();
      } catch (e){
  		// Internet Explorer Browsers
        try{
          XMLDocRequest = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
          try{
  	  XMLDocRequest = 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
      XMLDocRequest.onreadystatechange = function(){    
        if(XMLDocRequest.readyState == 4){
alert("debug message 1:ready state=");  
          XMLDoc = XMLDocRequest.responseXML;
        }
      }

alert("debug message 2:XMLFile="+XMLFile);
      XMLDocRequest.open("GET", XMLFile, false);	
      XMLDocRequest.setRequestHeader('Content-Type',  "text/xml");
      XMLDocRequest.send(null);
    } 
    
   function initPhotoShow(fileName){
        getXMLDoc(fileName);
alert("debug message 3:XMLDoc="+XMLDoc);
        var photos = XMLDoc.getElementsByTagName('photo');
alert("debug message 4:");
        //do clever things with the XML data ......
   }
  </script>
</head>


<body onload="initPhotoShow("<?php $inStr=$_GET['showName']; echo $showName; ?>")">
</body>

</html>

The contents of the XML file are:

<?xml version="1.0" encoding="ISO-8859-15"?>

<slides>
  <photo name="sbMapPhotos/sanBasilio.jpg" height="600" />
  <photo name="sbMapPhotos/touristOffice.jpg" height="435" />
  <photo name="sbMapPhotos/touristDock.jpg" height="460" />
</slides>

The symptoms of my problem are:

Debug message 1 never executes, and when I try to get information on the ready state ie- alert("debug message 1:ready state="+XMLDocRequest.readyState); the entire program fails to run.

Debug message 2 executes properly and prints the proper file name.

Debug message 3 executes and prints "undefined" as the XMLDoc

Debug message 4 never executes.

I have spent the last three days searching the web for the undoubtedly stupid mistake I am making, without success. Thank you in advance for pointing out where I have gone astray.

<body onload="initPhotoShow("<?php $inStr=$_GET['showName']; echo $showName; ?>")"> looks very suspicious.

What does the served version of this line look like?

Airshow

I don't know what you mean by "served version of this line", but the: alert("debug message 2:XMLFile="+XMLFile); debug message gets the proper file name parameter passed to it, which is the purpose of this onload code.

By "the served version" I mean what you see when you "view source" in your browser to see what's actually been served. You should typically do this a lot when page-building with a server-side language like PHP. <body onload="initPhotoShow("<?php $inStr=$_GET['showName']; echo $showName; ?>")"> is suspicious because (a) it establishes one variable then echos another and (b) you've got double quotes within double quotes in the HTML. However, if your debug message 1 is OK, then I guess it all works.

Try this. It's a (a) refactored and (b) SENSIBLY INDENTED version of your code.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<script language="javascript" type="text/javascript">
function xmlHttpRequest(){
  var r = false;
  try{ r = new XMLHttpRequest(); }// Opera 8.0+, Firefox, Safari
  catch (e) {
    // Internet Explorer Browsers
    try { r = new ActiveXObject("Msxml2.XMLHTTP"); }
    catch (e) {
      try { r = new ActiveXObject("Microsoft.XMLHTTP"); }
      catch (e) { alert("Your browser broke!"); return false; }// Something went wrong
    }
  }
  return r;
}
function initPhotoShow(fileName){
  var XMLDocRequest = xmlHttpRequest();
  if(!XMLDocRequest) return false;
  // Create a function that will receive data sent from the server
  XMLDocRequest.onreadystatechange = function() {
    alert("debug message 1:ready state=" + XMLDocRequest.readyState);
    if(XMLDocRequest.readyState == 4) {
      alert("debug message 4:");
      var responseXML = XMLDocRequest.responseXML;
      var photos = responseXML.getElementsByTagName('photo');
      // do clever things with the XML data ......
    }
  }
  alert("debug message 2:XMLFile=" + XMLFile);
  XMLDocRequest.open("GET", XMLFile, false);
  XMLDocRequest.setRequestHeader('Content-Type', "text/xml");
  XMLDocRequest.send(null);
  alert("debug message 3:XMLDoc="+XMLDoc);
}

onload = function(){
  initPhotoShow("<?php $inStr=$_GET['showName']; echo $showName; ?>")
}
</script>
</head>

<body>
</body>

</html>

Note in particular that the "// do clever things with the XML data ......" is now inside the response handler and debug message 1 should alert all response state changes.

Airshow

You will have to do a couple of fixes : fileName for XMLFile in initPhotoShow

commented: very helpful and responsive +0

Thanks for the hints, airshow. I did, indeed, pick up on the filename-xmlfile parameter problem: an artifact of my clumsy programming. Thanks also for the "Served version" tip. Your coding of the "onload" function is much more elegant than my obtuse quote nesting method. That will be useful in the future.

On my bicycle heading to the market to get supper fixings (the wife gets grumpy if not regularly fed), I realized that I had committed another newbie error in only testing the code in Firefox 3.5. on my return, I tested both your code and my code in IE and Chrome. Both code sets work perfectly in both of these browsers, so it is a Firefox problem. So, back to the search engines to research +XMLHttpRequest +firefox. If I find anything, I'll post it.

Thanks again!

Doug,

I have the answer!!

Moz browsers don't play ball with an AJAX request unless it's truly asynchronous, whereas IE and Chrome (so you inform me) do.

Change the line XMLDocRequest.open("GET", fileName, false); to read XMLDocRequest.open("GET", fileName, true); .

That third parameter determines asynchronous behaviour or not. For an attempt to explain "asynchronous" try this (by an author not a million miles away).

That should get the code working in FF.

Then you have to handle the response, which I would struggle with because you returning XML, which is awkward (some will demur) despite AJAX supposedly being all about XML. In fact you can return whatever you want (all HTTP requests and responses are just strings) as long as the javascript can do something sensible with it.

I would recommend (on the basis of personal experience) that you research Javascript Object Notation (JSON) which is SERIOUSLY simpler than XML both server-side and client-side. In essence, you json-encode your data in php and json-decode in javascript. This will save a lot of time and heartache. The Wikipedia entry on JSON is worth reading as is this.

I trust your supper went down OK. What bicycle do you ride?

Airshow

:) Thanks Airshow, that did it! The reason I had "false" for synchronous was the awkward way I had the code structured. I wanted to wait for the response before continuing processing. Your reformulation makes that unnecessary.

Thanks, too, for the tip on JSON. I will look into it, though I am very comfortable with XML. My background is in Geographic Information Systems (GIS) which has gone for XML in a big way, and I have spent many frustrating hours getting my head around it. The project for which I am writing this code is a Google Map mashup to which I am attempting to add a popup slide show capability. It is at visitsanblas in the dot com domain, in case you are interested. Click on the maps menu.

The Google Maps API has a function that opens XML files while hiding all the messy details in this code, but I wanted to avoid using it in this code because this is not really directly related to Google Maps. It would have been a lot easier, but I wouldn't have learned nearly as much.

Old dogs find it hard to learn new tricks, and coming from a structured programming background ('C' and Pascal), I am finding this freewheeling Javascript stuff a little disconcerting (sticking code snippets anywhere, creating variables on the fly without any typing--sort of takes the breath away). It will take some getting used to.

Supper went very well, homemade chicken noodle soup. The wife was pleased. Unfortunately I am not able to find any basil here in San Blas--the Mexicans don't seem to use it. I am trying to grow some, but the army ants are a formidable foe.

I ride a GIANT mountain bike, that does real well on the cobblestone streets that we have in San Blas. It is much more convenient to use that than to get in the car, bounce around on the bad streets, and then search for a parking spot.

Thanks again for all your help. Cheer!

Doug,

GIS/XML: I lurk on various AIS sites, keeping an eye on several favourite ships but thus far haven't needed to get into the data itself. XML is cool for general purpose data packaging but has no native support in javascript hence the popularity of JSON. Having said that, JSON native support is not yet universal - so you end up having to include a lib anyway!

Javascript does indeed take a bit of getting used to. Unusual features like "closure" and functions as first-class objects make it pretty mind-blowing if you come from just about any other programming background. I started out in Fortran in the mid '70s so I know all about learning new stuff. I work by the adage - "if you can do APL you can do anything". For javascript, you can do a lot worse than read as much as you can by Douglas Crockford. His video tutorials are very entertaining (in a geekish way).

San Blas: I had to look it up. Must be interesting. Your Giant will handle those cobbles better than my Raleigh Royal would - San Blas sounds like "700C-collapse City".

I'm into Tarragon (Estragón in Spanish according to Google) these days - goes into everything (except porridge).

Stay cool.

Airshow

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.