XML is a rather strict syntax, but if you need something quick ’n’ dirty then use the 1.0 version. (See the first line)
Basic rules are:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Country_Data> <!-- If you have troubles with this XML file (for example, the site no longer works after this was edited) then try running this through an XML validation tool such as http://validator.w3.org/#validate_by_input --> <version>1.1</version> <region name="Americas" sort="1" map="images/mapAmericas.png"> <countries> <name>United States</name> <name>Canada, English speaking</name> <name>Canada, French speaking</name> <name>Brazil</name> <name>Peru</name> </countries> <graph> <xAxis origin="2.78" min="2.55" max="3.15" /> <yAxis origin="2.91" min="2.85" max="3.1" /> </graph> </region> <dataPoints> <country name="United States" x="2.76" y="2.94" gfx="flags/UnitedStates.png" /> <country name="Canada, English speaking" x="2.79" y="2.95" gfx="flags/Canada.png" /> <country name="Canada, French speaking" x="2.81" y="2.88" gfx="flags/Canada.png" /> <country name="Norway" x="2.71" y="3.02" gfx="flags/Norway.png" /> <country name="Finland" x="2.75" y="2.98" gfx="flags/Finland.png" /> <country name="Sweden" x="2.79" y="2.93" gfx="flags/Sweden.png" /> </dataPoints> </Country_Data>
I’ve been using jQuery and it works rather well once you get your head wrapped around the process.
Beer.Datafile = function(filename) { this.version; this.regions = []; this.dataPoints = []; this.countryList = []; this.loadData(filename); } Beer.Datafile.prototype.loadData = function(filename) { jQuery.ajax({url: filename, context: this, dataType: 'xml', error: function(jqXHR, textStatus, errorThrown) { alert('Could not load ' + filename + '\ntextStatus='+textStatus+'\nerrorThrown='+errorThrown+'\njqXHR='+jqXHR); }, success: function(data){ //This code executes asynchronously AFTER the xml file has succesfully been loaded. var self = this; //the variable assigned to Beer.Datafile //find returns jQuery object of matched elements $(data).find('version').each(function(index) { self.version = $(this).text(); }); $(data).find('Country_Data').children('region').each(function(index) { //Process the geography var regionObj = { name:$(this).attr("name"), "sort":Number($(this).attr("sort")), map:$(this).attr("map"), countries:[], graph:{} }; $(this).children("countries").children("name").each(function(idx) { regionObj.countries.push($(this).text()); //country name }); $(this).children("graph").children().each(function() { var axisName = this.nodeName; regionObj.graph[axisName] = { origin:Number($(this).attr("origin")), "min":Number($(this).attr("min")), "max":Number($(this).attr("max")) } }); self.regions.push(regionObj); }); //Now that we have all the region/country info, sort the regions. self.regions = self.regions.sortBy(function(n) { return Number(n.sort); }); $(data).find('dataPoints').children().each(function(index) { //Process the (country) data points var dp = { country:$(this).attr("name"), x:Number($(this).attr("x")), y:Number($(this).attr("y")), gfx:$(this).attr("gfx") } self.dataPoints.push(dp); }); //Build a list of countries based on the Data Points for (var cntry=0;cntry<self.dataPoints.length;cntry++) { self.countryList.push(self.dataPoints[cntry].country); } //Make a hash table of data points by Country name for (var i=0; i < self.dataPoints.length; i++) { self.dataPoints[self.dataPoints[i].country] = self.dataPoints[i]; } initPage(); //Now that the file has been processed, begin the rest of the page scripts. } }); }
I found this comment on a blog talking about jQuery Deferreds. Looks like I may have to change the above code.
One of my big gripes with jQuery code that I see in the wild is that many people are not using the promise object methods when dealing with AJAX requests. Instead they are using the old success(), error() and complete(). jQuery has said in their docs that when 1.8 is released, those methods will be removed and you will then need to use the done(), fail() and always() correctly.