Section 13.5. Working with XMLor Not


13.5. Working with XMLor Not

In Example 13-1, the response was returned as a text string, with contents formatted as HTML. When it was added to the page, the entire select element was replaced because Microsoft does not support innerHTML for select directly. A better approach would have been to take the response and generate options, which are then added to the page. However, returning the string as already formatted options isn't optimal for processing.

Rather than format the options, you can return a string with the options concatenated with commas in between, such as the following:

return "Seattle,Olympia";

However, this isn't very effective if the data is more complex. For instance, in our example, the value of the option item is different from the string that's printed out. When you start returning text more complex than simple strings, the response gets more complicated.

For more complicated data, or data that you don't want formatted as HTML, there are two other options: XML or JSON (JavaScript Object Notation). Let's look at each of these approaches in turn.

13.5.1. Yes to XML

One advantage to returning a response formatted as XML is that the data can be much more complex than simple strings, or preformatted in HTML. In addition, there are several DOM methods that can process the data. After all, a web page is typically valid X(HTML) (we hope), and these methods can work on web pages.

Of course, using XML adds its own burdens. For instance, it's important that the server-side application return the property MIME type of text/xml for the content, or it won't end up in the responseXML container. In addition, the XML has to be valid XML, which means it has a root element that contains all of the other data. Example 13-3 shows the server-side application, ajaxxml.php, after it's written to return XML. Note that there are two elements for each city: value and title. The value is what's included within the option, and the title is what's printed out to the page.

Example 13-3. PHP Ajax application now returning XML

<?php //If no search string is passed, then we can't search if(empty($_GET['state'])) {     echo "<city>No State Sent</city>"; } else {     //Remove whitespace from beginning & end of passed search.     $search = trim($_GET['state']);     switch($search) {       case "MO" :          $result = "<city><value>stlou</value><title>St. Louis</title></city>" .                    "<city><value>kc</value><title>Kansas City</title></city>";          break;       case "WA" :          $result = "<city><value>seattle</value><title>Seattle</title></city>" .                    "<city><value>spokane</value><title>Spokane</title></city>" .                    "<city><value>olympia</value><title>Olympia</title></city>";          break;       case "CA" :          $result = "<city><value>sanfran</value><title>San Francisco</title></city>" .                    "<city><value>la</value><title>Los Angeles</title></city>" .                    "<city><value>web2</value><title>Web 2.0 City</title></city>" .                    "<city><value>barcamp></value><title>BarCamp</title></city>";          break;       case "ID" :          $result = "<city><value>boise</value><title>Boise</title></city>";          break;       default :          $result = "<city><value></value><title>No Cities Found</title></city>";          break;       }      $result ='<?xml version="1.0" encoding="UTF-8" ?>' .               "<cities>" . $result . "</cities>";    header("Content-Type: text/xml; charset=utf-8");     echo $result; } ?>

Once the server application is finished, the client-side application built into JavaScript must be changed. Example 13-4 shows the modified web page.

Example 13-4. Client application modified to work with an XML response

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Hello Ajax World, Too</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style type="text/css"> div.elem { margin: 20px; } </style> <script type="text/javascript"> //<![CDATA[ var xmlhttp = false; if (window.XMLHttpRequest) {    xmlhttp = new XMLHttpRequest(  );    xmlhttp.overrideMimeType('text/xml'); } else if (window.ActiveXObject) {    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } function populateList(  ) {    var state = document.forms[0].elements[0].value;    var url = 'ajaxxml.php?state=' + state;    xmlhttp.open('GET', url, true);    xmlhttp.onreadystatechange = getCities;    xmlhttp.send(null); } function getCities(  ) {    if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {      try {         var citynodes = xmlhttp.responseXML.getElementsByTagName('city');         for (var i = 0; i < citynodes.length; i++) {            var name = value = null;            for (var j = 0; j < citynodes[i].childNodes.length; j++) {               var elem = citynodes[i].childNodes[j].nodeName;               var nodevalue = citynodes[i].childNodes[j].firstChild.nodeValue;               if (elem == 'value') {                   value = nodevalue;               } else {                   name = nodevalue;               }            }            document.forms[0].elements[1].options[i] = new Option(name,value);          }       } catch (e) {             alert(e.message);       }    } else {       document.getElementById('cities').innerHTML = 'Error: No Cities';    } } //]]> </script> </head> <body> <h3>Select State:</h3> <form action="ajaxxml.php" method="get"> <div > <select onchange="populateList(  )"> <option value="CA">California</option> <option value="MO">Missouri</option> <option value="WA">Washington</option> <option value="ID">Idaho</option> </select> </div> <h3>Cities:</h3> <div > <select > </select> </div> </form> </body> </html>

Let's walk through the code to process the return.

First, the DOM function getElementsByTagName is called on the XML returned through the request's responseXML property. This gives us a set of child nodes for each city in the XML. Each child node, in turn, has two of its own: one for value, and one for the title element.

Instead of assuming that the XML that's returned to the web page is positionally dependent (value is always first, then title), the application traverses the nodeList for childNodes and gets the nodeName for each. This is compared to value and if a match occurs, its nodeValue is assigned to value. If not, the nodeValue is assigned to title (though this value could be tested first to ensure it is title). Once the city childNodes are traversed, the value and title are used to create a new option, and the next city processed.

All of this code is enclosed in exception handling because the DOM functions throw errors that aren't processed as such by the browser. It's a good habit to get into when you work with Ajax.

With the approach just demonstrated, no matter how deep the XML nesting, this same process can be used to access the nodes. After a while, though, you can see that the code could become cumbersome and hard to read or modify. It is this issue that generated interest in a new formatJSON.

If what you're after is an attribute and not a node, you can use the DOM getAttribute method to retrieve the value from the XML document. This is also part of the DOM Level 2 Core, as discussed in Chapter 10.


13.5.2. JavaScript Object Notation

As the web site that supports it claims, JSON, or JavaScript Object Notation, is "a lightweight data-interchange format." Rather than attempt to chain references as comma-delimited strings or have to deal with the complexity (and overhead) of XML, JSON provides a format that converts a server-side structure into a JavaScript object that can be used practically right out of the box.

JSON actually uses JavaScript syntax to define the objects. For an object, the syntax is curly braces surrounding members:

object{ } or object { string : value...}

For an array, it's elements and square brackets:

array[] or array[value,value,...,value]

The values specified follow the same rules for variables and associated values (strings or numbers) as defined for JavaScript in ECMA-262, Third Edition.

JSON, just as with the XML and HTML examples, can be manually encoded, because it is just another text string. However, there's growing support for JSON APIs in different programming languages used with web services, and most have encoders that encode or decode JSON transmitted data.

For our purposes, though, we'll manually create the data structure. Example 13-5 contains a new server application, ajaxjson.php, which now converts the data to JSON format. The structure used is an array of objects, each with a value and a title property.

Example 13-5. Working with simple JSON in PHP

<?php //If no search string is passed, then we can't search if(empty($_GET['state'])) {     echo "<city>No State Sent</city>"; } else {     //Remove whitespace from beginning & end of passed search.     $search = trim($_GET['state']);     switch($search) {       case "MO" :          $result = "[ { 'value' : 'stlou', 'title' : 'St. Louis' }, " .                     "{ 'value' : 'kc', 'title' :' Kansas City' } ]";          break;       case "WA" :          $result = "[ { 'value' : 'seattle', 'title' : 'Seattle' }, " .                    "  { 'value' : 'spokane', 'title' : 'Spokane' }, " .                    "  { 'value' : 'olympia', 'title' : 'Olympia' } ]";          break;       case "CA" :          $result = "[ { 'value' : 'sanfran', 'title' : 'San Francisco' }, " .                    "  { 'value' : 'la',      'title' : 'Los Angeles'   }, " .                    "  { 'value' : 'web2',    'title' : 'Web 2.0 City'  }, " .                    "  { 'value' : 'barcamp', 'title' : 'BarCamp'       } ]";          break;       case "ID" :          $result = "[ { 'value' : 'boise', 'title' : 'Boise' } ]";          break;       default :          $result = "[ { 'value' : '', 'title' : 'No Cities Found' } ]";          break;     }     echo $result; } ?>

To use the data structure in the web page, access the JSON-formatted data from the responseText property, and then pass it to the eval function to evaluate the structure and assign it to a local program variable. Example 13-6 is our web page now adjusted for a JSON data structure.

Example 13-6. Using JSON-structured data between server and client

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Hello Ajax World, Too</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style type="text/css"> div.elem { margin: 20px; } </style> <script type="text/javascript"> //<![CDATA[ var xmlhttp = false; if (window.XMLHttpRequest) {    xmlhttp = new XMLHttpRequest(  );    xmlhttp.overrideMimeType('text/xml'); } else if (window.ActiveXObject) {    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } function populateList(  ) {    var state = document.forms[0].elements[0].value;    var url = 'ajaxjson.php?state=' + state;    xmlhttp.open('GET', url, true);    xmlhttp.onreadystatechange = getCities;    xmlhttp.send(null); } function getCities(  ) {    if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {      try {          eval("var response = ("+xmlhttp.responseText+")");          var sel = document.getElementById("cities");          var name = value = null;          for (var i = 0; i < response.length; i++) {             name = response[i].title;             value = response[i].value;             document.forms[0].elements[1].options[i] = new Option(name,value);          }       } catch (e) {             alert(e.message);       }    } else {       document.getElementById('cities').innerHTML = 'Error: No Cities';    } } //]]> </script> </head> <body> <h3>Select State:</h3> <form action="ajaxjson.php" method="get"> <div > <select onchange="populateList(  )"> <option value="CA">California</option> <option value="MO">Missouri</option> <option value="WA">Washington</option> <option value="ID">Idaho</option> </select> </div> <h3>Cities:</h3> <div > <select > </select> </div> </form> </body> </html>

As you can see, the JSON method is simpler than the XML method, though perhaps not as simple as the straight HTML approach. However, don't let that make your decision for you. You may have no choice in how the data is sent, and have to process the results regardless of the format. In addition, when dealing with increasingly complex objects, using XML with XSLT to transform the XML into viewable material can end up being less work in the end.

If you're working directly with a data structure, such as a relational database or Resource Description Framework (RDF), chances are you'll either be dealing with comma-delimited data or XML in the first case, or XML in the latterand a specialized XML at that.

One other thing to consider is using XML that uses namespaces. This can annotate an element name to prevent a conflict in vocabularies; use something like content:name. There is a DOM function called getElementsByTagNameNS that takes a namespace as one of the parameters, but not all browsers support this, including Internet Explorer.


The point is, and I hope it has been demonstrated in these examples, that Ajax is extremely easy and simple to use, and you have options with how your data is transmitted between the server application and the client page.

Now, time for a little fun: Google Maps.




Learning JavaScript
Learning JavaScript, 2nd Edition
ISBN: 0596521871
EAN: 2147483647
Year: 2006
Pages: 151

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net