Sometimes you might want to send back data from JavaScript in XML format...maybe you're sending back some really complex data. You can parse it just as easily as you can on the PHP side...so long as you watch for these gotchas:
CLEAR THE OUTPUT BUFFER!
- Make sure to call
ob_clean(); before you echo back you XML! If a stray carriage return is outside a PHP start/end script delimiter you will otherwise be hosed!!
Make sure PHP sets the headers for XML!
Simply start your script like this: THANK GOODNESS FOR
THIS PAGE!
header('Content-Type: text/xml');
header("Cache-Control: no-cache, must-revalidate"); //A date in the past
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
If you do this, then in your JavaScript handler, you can do something like this (though see example below with error checking)
function server_callback()
{ if (ajax_r.readyState == 4)
{ if (ajax_r.status == 200)
{
var d = ajax_r.responseXML; // <<---- !!!!!!!!!
lines = d.getElementsByTagName('Line');
for (var i = 0; i < lines.length; i++)
{
draw_entry("-"+lines[i].childNodes[0].nodeValue);
} } } }
Note the highlighted line!. Normally, results from Ajax are in the
responseText variable, which is just straight text. To make that into an XML tree, you'd have to use something like
(new DOMParser()).parseFromString(ajax_r.responseText, "text/xml");, which is ugly and (with this info) unnecessary and doesn't work with IE anyway! But, as shown, so long as you set the headers correctly in PHP, the XML tree is ready to use as shown!
Attributes are handled differently!
I mean attributes as in the 'age' attribute shown below.
<Person age=36>Matt</Person>
With Firefox, it's easy:
element.attributes["age"].
With IE, it's simply an array:
element.attributes which you have to walk through, checking the
name and
value properties. Because of this, I'm not using attributes! I could find no one else on the web who's discovered this...
Handling errors
Inspired by
here I wrote this. It's really a good idea to do this checking carefully, because one slip in your XML and the browser will just give up and die on you.
if (ajax_r.readyState == 4)
{ if (ajax_r.status == 200)
{ var s = ajax_r.responseXML;
if (s.parseError) // IE's validation
{ if (s.parseError.errorCode != 0)
{
log_text(s.parseError.reason);
return;
// you can also look at 's.xml' for a raw dump of the XML it got
}
}
else // Firefox
{ // supposedly you should poke around with:
// new XMLSerializer().serializeToString(req.responseXML)
}
}
}
Beware the 4096 byte node limit
If the contents of the node are > 4096, the browser will break it up into 4096 byte chunks! So if you do this...
description_list = items[i].getElementsByTagName('Description')[0].childNodes[0].nodeValue;
...and the stuff between your
tags is > 4096 bytes,
description_list will have only the first 4096 chars!
But luckily it is easy to reassemble like this:
description_list =
items[i].getElementsByTagName('Description')[0].childNodes;
for (var j = 0 ; j < description_list.length; j++)
{
description += description_list[j].nodeValue;
}
--
MattWalsh - 15 Mar 2007