jQuery and XML revisited
Back in February of 2007 I wrote a post entitled Use jQuery expressions and AJAX to browse an XML file. The jQuery library has changed quite a bit since then, and I have decided to revisit jQuery and XML with an intermediate tutorial. Much of this tutorial is written as a response to questions I have received from other developers in regards to the February post. I hope you enjoy it.
In releasing jQuery v.1.2, a decision was made by the development team to drop XPath support from the core. Instead, an officially released XPath jQuery plugin is now available, which provides deprecated functionality. Although initially disappointed by this decision, I was happy to discover that alternative methods for obtaining data from an XML file are still available without the plugin.
The first code snippet begins with the jQuery equivalent of the window onload event, and then immediately following is the familiar $.ajax() implementation. I make a GET request for an XML file named dbug.xml, specify the return type as XML, then pass it through the success function as the variable xml. A ZIP file is available for download at the end of this post, and it contains the XHTML, JavaScript and XML file referenced here.
$(function() {
$.ajax({
type: "GET",
url: "dbug.xml",
dataType: "xml",
success: function(xml) {
/* Count elements */
var count = jXML.getCount(xml,{"Channel":"channel","Item":"item:has(title)","GUID":"guid[isPermaLink]:lt(3)"});
alert( count["Channel"] + ", " + count["Item"] + ", " + count["GUID"] );
/* Return objects with a specific attribute */
var attribute = jXML.getAttribute(xml,{"GUID":["guid","isPermaLink",null],"Channel":["channel","id",null]});
alert( attribute["GUID"] + ", " + attribute["Channel"] );
/* Return objects with a specific attribute value */
var attribute = jXML.getAttribute(xml,{"GUID":["guid","isPermaLink","false"],"Channel":["channel","id","channel_1"]});
alert( attribute["GUID"] + ", " + attribute["Channel"] );
/* Return a number of objects randomized */
var random = jXML.getRandomObj(xml,{"Title":["item:has(title) > title",null],"URL":["item:has(link) > link",3]});
for (i = 0; i < random["Title"].length; i++) {
alert( $(random["Title"][i]).text() );
}
for (i = 0; i < random["URL"].length; i++) {
alert( $(random["URL"][i]).text() );
}
}
});
});
I will be using object literal notation in the tutorial, and the object that will process the XML is named jXML. There are three methods that exist in jXML: getCount, getAttribute, and getRandomObj. The second method (getAttribute) can perform two “functions”, depending on the parameters you pass through to it. The alerts are used only to let you know what type of response you are receiving back. In a production environment you would probably append this information to the DOM.
getCount
The getCount method will retrieve the number of element(s) that you specified from the XML. Each method, including getCount, really only takes two parameters: the xml reference, and a hash. The hash is also referred to as an associative array in Javascript. It is designated by an open curly brace, a key string in quotes, a colon, a value, and a close curly brace. Each key/value pair is separated by a comma. For example:
{"key":value,"key":value,"key":value}
With an associative array you can loop through values referencing the key, instead of an index. This works well for this tutorial, since the XML node names are distinct. Like indexed arrays, a hash value can be any data type, or object, including another array. In the first method getCount, a jQuery selector is used as a parameter value. However, in the other methods, an array containing several values is used as a parameter.
getAttribute
The getAttribute method retrieves only nodes (elements) as objects that contain a specific attribute. For instance, I want to find the guid node only if it contains an isPermaLink attribute. Leave the third value in the array null, or else you will be looking for an element with an attribute that also contains a specific value. The value that you want your attribute to contain would be this third value in the array.
The strings that are used as selectors in the example can be considered XPath substitutes, but any valid jQuery selector is appropriate. The following are only a few of the selectors that jQuery supports, and how each can be identified using plain English. To learn more about selectors supported by jQuery, you can visit the jQuery selector documentation page.
Get each guid node, or:
guid
Get each guid node that has an isPermaLink attribute with an index less than three, or:
guid[isPermaLink]:lt(3)
Get each item node that has a title child node, or:
item:has(title)
Get each title node that has an item parent node, or:
item > title
getRandomObj
The third, and most complicated method, will randomly select the number of and name of the node(s) that you specify. This method is great for a situation when any number of random elements are a sufficient data sampling. As opposed to the getAttribute method, which will alert “[Object object]”, the example demonstrates how to loop through the results returned. Remember, you are actually getting back an array object of objects, and you must loop through to each object individually.
var jXML = {
getCount: function(xml,nodes) {
var response = {};
for (var node in nodes) {
response[node] = $(nodes[node],xml).length;
}
return response;
},
getAttribute: function(xml,nodes) {
var response = {};
for (var node in nodes) {
if (nodes[node][2] == null) {
response[node] = $(nodes[node][0] + "[" + nodes[node][1] + "]",xml);
} else {
if ($(nodes[node][0],xml).attr(nodes[node][1]) == nodes[node][2]) {
response[node] = $(nodes[node][0],xml);
}
}
}
return response;
},
getRandomObj: function(xml,nodes) {
var response = {};
for (var node in nodes) {
var a = [];
var b = [];
$(nodes[node][0],xml).each(function(i) {
b[i] = this;
});
var c = b.length;
if (nodes[node][1] != null && nodes[node][1] < c) {
c = nodes[node][1];
}
for (i = 0; i < c; i++) {
var e = Math.floor(Math.random() * b.length);
a[i] = b[e];
b.splice(e,1);
}
response[node] = a;
}
return response;
}
};
I will not walk through every detail of each method in the jXML object, but I will highlight a few commonalities between all the methods. Take a look at the getCount method, and pay special attention to the selector within the for loop. The nodes[node] snippet is a reference to the parameter passed through in the hash, which is then used as the actual selector. In this instance, it would be channel, item:has(title) and guid[isPermaLink]:lt(3).
In the other methods that take an array as the hash value, the syntax is slightly different. The addition of the brackets and an index number allows you to access specific elements in the array, such as nodes[node][1]. In the getAttribute method this is used to provide the attribute name that you wish to use in the selector, such as id and isPermaLink.
The final note is regarding the response sent back to the variable in each method call. To make it more manageable in development, the key/value pairs returned use the same keys as when passing the parameters. This prevents the mess of having to match up the keys sent with an indexed array returned. I tried to optimize getRandomObj as best as possible, but if anyone has suggestions, please share them in the comments.
Leave a Comment
Comments are moderated. No profanity. Only <a>...</a>, <blockquote>...</blockquote>, and <code>...</code> are allowed.
Seperate paragraphs by pressing the "Enter" key twice, or press it once to break to a new line.
18 Comments
#01, Sep 25 2007
Alex
Hi there,
Great tutorial it’s definitely helped, however I’m struggling to create a live-search/auto-suggest/auto-complete/whatever that searches an xml file.
Any suggestions or even better could you please do another fantastic tutorial?
Many thanks
#02, Sep 25 2007
Brian
Hi Alex,
I would suggest having a look at the jQuery plugins page. There are some great auto-complete plugins that already exist and that might suit your needs.
Brian
#03, Sep 27 2007
links for 2007-09-28 « Simply… A User
[…] jQuery and XML revisited » d’bug (tags: jquery xml javascript ajax tutorial development programming webdev **) […]
#04, Sep 30 2007
links for 2007-09-30 « toonz
[…] jQuery and XML revisited » d’bug (tags: jquery xml ajax tutorial webdev) […]
#05, Oct 01 2007
rascunho » Blog Archive » links for 2007-10-01
[…] JQuery xml (tags: blog.reindel.com 2007 mes9 dia1 at_tecp jquery xml blog_post) […]
#06, Oct 02 2007
Ajaxian » Ajaxian Featured Tutorial: Parse JSON with jQuery and JavaScript
[…] jQuery and XML revisited Parse JSON with jQuery and JavaScript […]
#07, Oct 24 2007
Bruno
I have to admit that this is a nice tutorial, but on my Internet Explorer it does absolutely nothing… no errors neither any result.
IE version is 6.0 on windows xp sp2
#08, Oct 24 2007
Brian
Hi Bruno,
Are you using the IE6 downloaded from Evolt.org, IE6 from “Multiple IE”, or a computer simply with IE6 installed? The reason I ask is that in standalone IE6 from Evolt.org, ActiveX is not supported, which would explain why it is not working. I hope I can be of some assistance.
#09, Nov 02 2007
Learning jQuery » Tutorials Elsewhere
[…] jQuery and XML Revisited. Brian Reindel walks through a few methods he wrote to handle XML retrieved via xhr. […]
#10, Nov 05 2007
mulling.net
[…] jQuery and XML revisited » dâ��bug - […]
#11, Jan 24 2008
Brian S
What fun! I never realized you could use jQuery to search through XML documents like this. I’m very glad you posted this :)
#12, Feb 10 2008
Kevin
Great tutorial, but I’ll have to echo Bruno’s comment — it’s not working for me on IE6. ActiveX is definitely supported and enabled, but still no luck….
#13, Mar 18 2008
Martin Sarsini
It’s a nice jquery functionality, it will be nice to see more about the “get content” inside each xml tag
#14, Mar 18 2008
Martin Sarsini
For Bruno and Kevin, for me it wasn’t working either.
Perfect on Firefox, not working on IE.
The XML file didn’t had the right headers, save the file in .xml or if generated by php add header(”Content-type: application/xml”)
#15, Mar 20 2008
Brian
Hi Martin,
Thanks for commenting and for sharing that fix!
Brian
#16, Mar 24 2008
jQuery.getJSON « Mashuphowto’s Weblog
[…] jQuery and XML revisited Parse JSON with jQuery and JavaScript […]
#17, Apr 02 2008
65 Excellent jQuery Resources (tutorials,cheat sheets,ebooks,demos,plugins…) | Speckyboy - Wordpress and Design
[…] with jQuery 25. JQuery Pop-up Menu Tutorial 26. A Quick Code Igniter and JQuery Ajax Tutorial 27. jQuery and XML revisited 28. What is JSONP? 29. Creating A Sliding Image Puzzle Plug-In 30. Slide out and drawer effect 31. […]
#18, Jun 15 2008
Khaled
Hi,
I have a problem in IE, I saw all the comments and I have the right headers.
Also, I downloaded the code from here, but it’s not working in IE7 (Vista and XP).
so what should I do ?