jQuery Demo: Working With XML Documents

Posted November 27, 2007 at 7:05 AM

Tags: ColdFusion, Javascript / DHTML

As we learn about AJAX (Asynchronous Javascript and XML), our first thought is that it is very cool. Our second thought is usually that XML sucks and it's such a pain in the butt to work with. With that discovery, many of us turn to using AJAX purely as a text/HTML delivery system or we switch to using JSON (Javascript Object Notation) which is infinitely easier to work with on the client. And, while I tend to go with JSON for my AJAX functionality, let's not forget that XML is a very cool delivery format.

If you have to use XML, you might want to consider using jQuery as well. It's very rare that you see any examples of jQuery being used with XML, but the fact is, all the features that make jQuery so amazing for XHTML traversal and searching also hold true for XML documents. The jQuery factory method ($) can take, as one of it many data types, an XML document object model. Once you do this, you can pretty much use the resultant jQuery stack as if it were an XHTML document object model (which should make you much more comfortable).

To demonstrate this, let's set up a rather simple ColdFusion page that just returns some XML data to an AJAX request:

 Launch code in new window » Download code as text file »

  • <!--- Build the XML into a ColdFusion XML document. --->
  • <cfxml variable="xmlGirl">
  •  
  • <person type="girl">
  •  
  • <head>
  • <eyes value="brown" />
  • <hair value="brown" />
  • </head>
  •  
  • <torso>
  • <bust value="34A" />
  • <navel value="pierced" />
  • </torso>
  •  
  • <legs>
  • <waist value="24" />
  • <hips value="36" />
  • <calves value="22" />
  • </legs>
  •  
  • </person>
  •  
  • </cfxml>
  •  
  •  
  • <!--- Convert XML to a string. --->
  • <cfset strGirlXml = Trim( ToString( xmlGirl ) ) />
  •  
  •  
  • <!---
  • Set the length of the content. This will help the browser
  • know when the request is completel.
  • --->
  • <cfheader
  • name="content-length"
  • value="#Len( strGirlXml )#"
  • />
  •  
  • <!---
  • Set the XML document type. This will help the AJAX calling
  • program to determine which type of data is being returned
  • (XML, JSON, Script, etc).
  • --->
  • <cfcontent
  • type="text/xml"
  • variable="#ToBinary( ToBase64( strGirlXml ))#"
  • />

Notice that we are building the XML document using ColdFusion CFXml tags. We could have easily done this same task using ColdFusion's CFSaveContent tag for buffered output, but I think there is something nice about using CFXml to ensure that only proper XML structures are created. This ColdFusion XML document is then converted to a string and streamed back to the client.

Ok, now that we have our XML feed set up (girl.xml.cfm), let's create the HTML page that will consume this data:

 Launch code in new window » Download code as text file »

  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <html>
  • <head>
  • <title>jQuery Demo: Using jQuery With XML</title>
  •  
  • <!-- Linked files. -->
  • <script type="text/javascript" src="jquery-latest.pack.js"></script>
  • <script type="text/javascript">
  •  
  • // This function will handle the xml Onload event
  • // handler. It will be passed the XML data object
  • // and the status of the XmlHttpRequest object.
  • function XmlOnLoad( xmlData, strStatus ){
  • // Let's start out by converting the XML data
  • // returned by the AJAX request into a jQuery
  • // XML document object model.
  • var jData = $( xmlData );
  •  
  • // Get the person object (but only if it is a girl).
  • var jGirl = jData.find( "person[ type = 'girl' ]");
  •  
  • // Get the direct children of the girl. These
  • // will represent the sections of the body.
  • var jSections = jGirl.children();
  •  
  • // For each of the section, we want to create
  • // an element in the girl definition list. Get a
  • // pointer to said definition list.
  • var jList = $( "#girl" );
  •  
  •  
  • // For each section, create a list item.
  • jSections.each(
  • function( intSectionIndex ){
  • var jSection = $( this );
  • var jTerm = $( "<dt></dt>" );
  •  
  • // Set the term text.
  • jTerm.text( jSection[ 0 ].nodeName );
  •  
  • // Append term to list.
  • jList.append( jTerm );
  •  
  •  
  • // Now, for each part of the section, we are
  • // going to need to create a list.
  • jSection.children().each(
  • function( intPartIndex ){
  • var jPart = $( this );
  • var jDef = $( "<dd></dd>" );
  •  
  • // Set the DD text.
  • jDef.text(
  • " - " +
  • jPart[ 0 ].nodeName + ": " +
  • jPart.attr( "value" )
  • );
  •  
  • // Append to list.
  • jList.append( jDef );
  • }
  • );
  • }
  • );
  • }
  •  
  •  
  • // When the document has loaded, request the girl
  • // XML object which will then use to populate the
  • // XHTML document.
  • $(
  • function(){
  • $.get(
  • "girl.xml.cfm",
  • {},
  • XmlOnLoad
  • );
  • }
  • );
  •  
  • </script>
  • </head>
  • <body>
  •  
  • <h1>
  • jQuery Demo: Using jQuery With XML
  • </h1>
  •  
  • <dl id="girl"></dl>
  •  
  • </body>
  • </html>

This code looks complicated because there are a lot of comments, but really, it's quite simple. The magic here is that in my AJAX callback method, I am taking the returned XML document and creating a jQuery stack object:

 Launch code in new window » Download code as text file »

  • var jData = $( xmlData );

jData, our jQuery instance object, now contains the XML document object model (#document) which can be traversed using any of jQuery's sweet ass functions (ex. find(), children(), parent(), etc.).

The code of our page takes the XML document, which defined body parts, and uses the data to populate a Definition List. Running the above code, we get:

jQuery Demo: Using jQuery With XML

head
- eyes: brown
- hair: brown
torso
- bust: 34A
- navel: pierced
legs
- waist: 24
- hips: 36
- calves: 22

So, while raw XML can be complicated to work with, using XML in conjunction with jQuery can make things much easier. I am not advocating using this over JSON, as I think JSON is the bee's knees; but certainly, in a scenario where XML is your only option (as it might be with something like centralized input validation), jQuery is certainly something you're gonna want to check out.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page



Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

Reader Comments

Nov 27, 2007 at 1:38 PM // reply »
2 Comments

Thanks for the excellent article! I was trying to work out how to use jQuery with XML a few weeks back and this article clears things up perfectly! :D


Nov 27, 2007 at 1:51 PM // reply »
5,406 Comments

@Guy,

Glad to help. Yeah, you really don't see many examples with this. Most of the time, just a footnote about "This also works with XML". So, I figured I would put this out there.


Nov 30, 2007 at 7:14 AM // reply »
18 Comments

Hi Ben,

Good article. I haven't looked into JQuery yet (only CF8 Ajax functions and Spry) but it's something I do want to experiment with and this will help.

I do have a question though. Why are you converting the XML to base64 and then to binary - I couldn't figure out why that was necessary.


Nov 30, 2007 at 12:05 PM // reply »
5,406 Comments

@James,

I do that because I find using the CFContent tag to set the type of data and stream the data quite convenient. By streaming a binary variable, the CFContent takes care of all the white space management. With an XML file, you have to be careful not to return leading white space (or at least it is best practice). By streaming the variable, you know for sure that none of the pre-page processing will cause the XML data to be malformed.


bay
May 23, 2009 at 4:32 AM // reply »
1 Comments

great article!
here's a quick question..
I'm very VERY new to all this...
so I'm rack my brain trying to get how ajax and jquery all work.
say if I have three buttons...each with ID 1, 2, and 3.
I have an xml file with 3 different pieces of info each with an id of 1, 2, and 3 as well. How would I make a string that takes the id of the button...matches it to the ID of the xml...then spits out the corresponding info?


Post Comment  |  Ask Ben

Recent Blog Comments
Jul 4, 2009 at 4:00 AM
Terms Of Service / Privacy Policy Document Generator
thanks ben, I'm not a big fan of contracts so to find your no no-nesense ToS generator has helped me no end. all the best matt ... read »
Justice
Jul 3, 2009 at 11:10 PM
Create A Running Average Without Storing Individual Values
@Ben, I think you're going about this the wrong way. You're trying to use complicated techniques when there is a simple and beautiful technique readily available (a la Gary Funk's comment). Instead ... read »
Bob
Jul 3, 2009 at 9:19 PM
Project HUGE: Huge In A Hurry - Get Big - Phase 3 / Week 1
a good technical explanation http://crossfitphoenix.typepad.com/crossfit_phoenix_forging_/the-overhead-squat.html ... read »
Jul 3, 2009 at 9:03 PM
Create A Running Average Without Storing Individual Values
If I wanted to do this and only carry two numbers, I'd keep track of the sum and N. Then you are pretty much accurate all the time. average = (sum + new_number) / (N + 1) But all this was in a for ... read »
Roland Collins
Jul 3, 2009 at 8:58 PM
Create A Running Average Without Storing Individual Values
@Martin - not just floating point though. Depending on what langauge you're working in, decimals can cause just as many headaches if they're not precise enough. But again, for most applications, th ... read »
Isnogood
Jul 3, 2009 at 7:16 PM
Project HUGE: Huge In A Hurry - Get Big - Phase 3 / Week 1
Watch this http://www.nsca-lift.org/videos/default.shtml ... read »
Aaron
Jul 3, 2009 at 7:13 PM
Project HUGE: Get Big, Phase One (Chat Waterbury - Huge In A Hurry)
I've just finished the 3rd week of phase 3, and have to agree that the overhead squats are hard. I think this is most due to the wide grip on which places more pressure on your upper back. Only this ... read »
Isnogood
Jul 3, 2009 at 7:11 PM
Project HUGE: Huge In A Hurry - Get Big - Phase 3 / Week 1
Very good, there were some near perfect reps, and there were some dodgy ones, but you're getting there your body position is good. Work on your depth and do not let the bar move forward or backward, ... read »