Retrieving an XML document using Ajax
When making a server request in Ajax, the data returned can be in either plain text/html, or an XML document instead. The later is technically just a text file as well, but with some special instructions, Ajax can retrieve that well formed XML text file and return it back to you as a XML object. This enables the XML data to be easily parsed using standard DOM methods.
Here's a simple XML document in RSS format I'll be using for illustration (lets name it "javascriptkit.xml"):
<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="0.91">
<channel>
<title>JavaScriptKit.com</title>
<link>http://www.javascriptkit.com</link>
<description>JavaScript tutorials and over 400+ free scripts!</description>
<language>en</language>
<item>
<title>Document Text Resizer</title>
<link>http://www.javascriptkit.com/script/script2/doctextresizer.shtml</link>
<description>This script adds the ability for your users to toggle your
webpage's font size, with persistent cookies then used to remember the
setting</description>
</item>
<item>
<title>JavaScript Reference- Keyboard/ Mouse Buttons Events</title>
<link>http://www.javascriptkit.com/jsref/eventkeyboardmouse.shtml</link>
<description>The latest update to our JS Reference takes a hard look at
keyboard and mouse button events in JavaScript, including the unicode value
of each key.</description>
</item>
<item>
<title>Dynamically loading an external JavaScript or CSS file</title>
<link>http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml</link>
<description>External JavaScript or CSS files do not always have to be
synchronously loaded as part of the page, but dynamically as well. In this
tutorial, see how.</description>
</item>
</channel>
</rss>
The below shows retrieving this XML document and outputing the headlines
("title
" elements) of each entry:
<div id="result"> </div>
<script type="text/javascript">
function ajaxRequest(){
var activexmodes=["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"] //activeX
versions to check for in IE
if (window.ActiveXObject){ //Test for support for ActiveXObject in IE first
(as XMLHttpRequest in IE7 is broken)
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 mygetrequest=new ajaxRequest()
if (mygetrequest.overrideMimeType)
mygetrequest.overrideMimeType('text/xml')
mygetrequest.onreadystatechange=function(){
if (mygetrequest.readyState==4){
if (mygetrequest.status==200 || window.location.href.indexOf("http")==-1){
var xmldata=mygetrequest.responseXML //retrieve result
as an XML object
var rssentries=xmldata.getElementsByTagName("item")
var output='<ul>'
for (var i=0; i<rssentries.length; i++){
output+='<li>'
output+='<a
href="'+rssentries[i].getElementsByTagName('link')[0].firstChild.nodeValue+'">'
output+=rssentries[i].getElementsByTagName('title')[0].firstChild.nodeValue+'</a>'
output+='</li>'
}
output+='</ul>'
document.getElementById("result").innerHTML=output
}
else{
alert("An error has occured making the request")
}
}
}
mygetrequest.open("GET", "javascriptkit.xml", true)
mygetrequest.send(null)
</script>
Demo:
The key points to remember when getting a XML document using Ajax are:
- Detect for and call the method
request.overrideMimeType('text/xml')
before sending the request. This is a necessary step to address an issue in certain versions of Firefox. IE has much bigger problems- see next section below. - When accessing the returned data, call
request.responseXML
instead ofresponseText
to get the data as an XML object (assuming the data is a valid XML file).
The data returned by request.responseXML
is an XML object
that can be parsed using standard
DOM methods and properties.
Notice that to access the actual contents of an element, you need to drill
down all the way to the element's "firstChild
" object before
looking up its "nodeValue
".
XML documents and the "Content-type" pitfall in IE
There is a major pitfall to be aware of when getting XML documents via
Ajax in IE (as of IE7). Not knowing this will have you pulling your hair
out wondering why you can't work on the returned data as an XML object.
So what's this giant hole in the ground? Well, in IE, XML documents must
return an explicit "content-type
" header corresponding to
XML (ie: "Content-type: text/xml
") in order for the browser
to know that this is an XML document. Without this header, the file will
be retrieved as a regular text file instead of turning its contents into
an XML object. Firefox has this requirement as well actually, though
instead of solely relying on the server to hopefully generate the
correct "content-type
" header for a given file, it supports the
client side method "request.overrideMimeType()
" that you
can use to just tell the browser manually and unequivocally what the type of
the target file is. That's why we call the lines:
if (mygetrequest.overrideMimeType)
mygetrequest.overrideMimeType('text/xml')
in the code earlier in Firefox, so FF is told manually that
the target file is an XML one. Any question, either coming from the
server end or the browser's with regards to what the heck the type of
the target file is instantly silenced by calling this method, no
problem. However, IE the rebel doesn't support "request.overrideMimeType()
",
which means you must rely fully on your server- and tweak it if
necessary- to properly generate the correct "content-type
"
headers for XML documents. No proper header, and the file will be
returned as plain text, instead of an XML object that you access using "request.responseXML
".
Typically a server is already set up to generate the proper "content-type
"
headers for the well known file extensions, such as "text/xml
"
for all files with an ".xml
" extension. Assuming this is
the case on your server and the file you're retrieving via Ajax is
called "sample.xml", then you won't run into any problems in IE, as the
correct XML header has been added. But consider all the other possible
situations in which you would:
- Your server isn't set up to recognize ".xml" files as XML documents.
- You named the XML file with a custom extension such as "sample.rss"
- Your XML file is dynamically generated via a server side script, so its extension may be "sample.php"
For 1) and 2), the solution is to modify your server's configuration to output a correct XML content mimetype based on the file extensions that should be recognized as XML documents. On Unix/Linux servers for example, this can usually be done in one of two ways:
1) Add to the ".htaccess
" file that exists in the HTML
root directory of your site the line (more
info):
AddType application/xml .xml .rss
2) OR, at an even lower level, add the above line to the "httpd.config
"
file of your server instead (look under the "mimetypes
"
section). Alternatively, if your server uses a graphical control panel
such as cPanel, you can just click
on the "Mime Types" button on the admin frontpage to make the
changes.
For 3), the solution is simpler. If your XML file is dynamically generated by a server side script, simply ensure that the script outputs an XML header before the actual XML contents. Using a PHP script for example, you'd do:
<?
header('Content-type: text/xml');
echo "Actual XML contents...";
?>
Yes, curse the day IE was born!
- Performing GET requests using Ajax (Ajax introduction)
- Performing POST requests using Ajax
- Retrieving an XML document using Ajax
- Retrieving a JSON file using Ajax