| 
  Introduction to XML in Flash by senocular
 
 Example: Sorted Grades 
                                  ListEditing XML can be a pain. If you have data 
                                  that needs to be sorted, you wouldn't want to 
                                  do that directly from the XML instance. Instead, 
                                  you could be better off handling it through 
                                  an array as arrays have sort functions built 
                                  right in. Because of how a childNodes array 
                                  works, as an array copy representative of the 
                                  XML node structure, we can keep XML node references 
                                  in an array from a childNodes call and just 
                                  use that to sort and handle our data. If things 
                                  go horribly wrong, the original data in the 
                                  XML instance will remain in its original order 
                                  without disruption. Using a childNodes array 
                                  still means that we'd be working from XML nodes 
                                  from the XML instance, but the original order 
                                  will remain unchanged for the XML instance. 
                                  This example shows sorting performed on a childNodes 
                                  array copy that has no effect on the internal 
                                  XML instance order.
 So, starting with this list of students in 
                                  no particular order: 
                                  <?xml version="1.0" 
                                    ?><grades year="1994">
                                    <student 
                                      first="James" 
                                      last="Johnson" 
                                      gpa="3.3" 
                                      /><student 
                                      first="John" 
                                      last="Smith" 
                                      gpa="4.0" 
                                      /><student 
                                      first="Serena" 
                                      last="Williams" 
                                      gpa="3.8" 
                                      /><student 
                                      first="Indiana" 
                                      last="Jones" 
                                      gpa="3.2" 
                                      /><student 
                                      first="Linda" 
                                      last="Brown" 
                                      gpa="3.9" 
                                      /><student 
                                      first="Robert" 
                                      last="Davis" 
                                      gpa="3.2" 
                                      /><student 
                                      first="Seno" 
                                      last="Cular" 
                                      gpa="4.0" 
                                      /><student 
                                      first="Mike" 
                                      last="Wilson" 
                                      gpa="3.0" 
                                      /><student 
                                      first="Mary" 
                                      last="Moore" 
                                      gpa="3.0" 
                                      /><student 
                                      first="Will" 
                                      last="Taylor" 
                                      gpa="2.5" 
                                      /><student 
                                      first="Thomas" 
                                      last="Anderson" 
                                      gpa="2.1" 
                                      /><student 
                                      first="David" 
                                      last="Thomas" 
                                      gpa="3.7" 
                                      /> </grades> (Which can be found here: grades_1994.xml) You can use the power of Array.sort() on a 
                                  childNodes array to rearrange them and display 
                                  them at will:  
                                   [ 
                                  sort student grades using column headings ]   Preparing the Flash FileThe XML document containing students to be sorted 
                                  uses 3 attributes: first names, last names and 
                                  gpa. Without using any fancy-schmancy components, 
                                  we can handle this using three separate, multi-lined 
                                  (non-wrapping) text fields, one for each attribute. 
                                  Above each will go the section headings which 
                                  will also pose as buttons for sorting. Again, 
                                  one for each attribute labeled accordingly.
 
 [ 
                                  three columns with text fields and a buttons 
                                  ] In addition to those buttons, an extra is added 
                                  to restore order back to that which was specified 
                                  in the original XML document. 
 [ 
                                  restore button ] This is just a copy of all the others with 
                                  a different name so its really no big deal. 
                                  And, in fact, the script that is associated 
                                  with this is far less complicated as well. ActionScriptThe bulk of this example revolves around array 
                                  sorting. Like many of the simpler examples from 
                                  before, the XML itself is loaded once and for 
                                  the most part discarded. Everything after the 
                                  content is loaded revolves around an array that 
                                  is assigned as a childNodes array of one of 
                                  the elements of the XML, more specifically the 
                                  document root or the grades element.
 So lets check out some ActionScript. First, 
                                  the XML instance: 
                                  var students_array;var grades_xml 
                                    = new 
                                    XML();grades_xml.ignoreWhite 
                                    = true;grades_xml.onLoad 
                                    = function 
                                    (success) 
                                    {
                                    if (success) 
                                      {
                                      var grades 
                                        = this.firstChild;students_array 
                                        = grades.childNodes;PopulateLists(students_array); } else 
                                      {
                                      trace('Error 
                                        loading XML file.'); } }grades_xml.load('grades_1994.xml'); For the most part typical. The difference here 
                                  is the addition of a students_array variable 
                                  and the fact that the function being called 
                                  from the onLoad to handle the loaded content 
                                  doesn't specifically pass the XML instance or 
                                  one of its nodes. Rather, it gets the students_array 
                                  which had been just assigned to a childNodes 
                                  array from the grade element (which is the XML 
                                  instance's first child or the XML document's 
                                  root). This array initially has the order of 
                                  the XML but can be altered without altering 
                                  the XML order. The contents of the array are 
                                  references to XML nodes. If they were altered, 
                                  as references, they would actually affect the 
                                  XML. Here is the PopulateLists function: 
                                  PopulateLists 
                                    = function(xml_array){
                                    first_txt.text 
                                      = last_txt.text 
                                      = gpa_txt.text 
                                      = "";for (var 
                                      i=0; 
                                      i<xml_array.length; 
                                      i++){
                                      var student 
                                        = xml_array[i].attributes;first_txt.text 
                                        += student.first 
                                        + "\n";last_txt.text 
                                        += student.last 
                                        + "\n";gpa_txt.text 
                                        += student.gpa 
                                        + "\n"; } } First the text in the text fields that make 
                                  up the columns is cleared by setting them each 
                                  to "". 
                                  first_txt.text 
                                    = last_txt.text 
                                    = gpa_txt.text 
                                    = ""; 
                                 Then, a for loop is created to cycle through 
                                  all the elements within the passed array. Since 
                                  these elements are references to nodes, they 
                                  will give us access to the XML. Conveniently, 
                                  a properly named variable is immediately created 
                                  to reflect that XML information (it could be 
                                  used to represent the element but since we're 
                                  dealing with attributes only here, it can be 
                                  assigned to reference the attributes object). 
                                  for (var 
                                    i=0; 
                                    i<xml_array.length; 
                                    i++){
                                    var student 
                                      = xml_array[i].attributes;// ... } Now all that remains is adding the information 
                                  from each node within the loop to their respective 
                                  columns. 
                                  first_txt.text 
                                    += student.first 
                                    + "\n";last_txt.text 
                                    += student.last 
                                    + "\n";gpa_txt.text 
                                    += student.gpa 
                                    + "\n"; Because each text field is getting a new line 
                                  of text at the same time, the information will 
                                  match horizontally. Once the loop is complete, 
                                  the columns will be populated with all the students 
                                  in the XML; first and last names and gpa. All that remains is being able to sort these 
                                  guys. That poses no considerate problem considering 
                                  that an array is used to maintain order. However, 
                                  what that doesn't mean there is no 
                                  problem. There is still the issue of what to 
                                  sort by. Considering we have three 
                                  different categories to sort by, first, last 
                                  and gpa, it means that every array element within 
                                  students_array would have to be able to be sorted 
                                  by any one of those 3 properties. To handle 
                                  this, we need to create custom sort functions 
                                  to use with Array.sort(). Otherwise, sort will 
                                  just sort the XML nodes alphabetically based 
                                  on their string representations. Custom sort 
                                  functions would allow us to specifically pin 
                                  point the part of the node we wish to sort by. 
                                  Here's what we get in terms of sort functions: 
                                  FIRST_SORT 
                                    = function(a,b){
                                    return a.attributes.first 
                                      > b.attributes.first; }LAST_SORT = 
                                    function(a,b){
                                    return a.attributes.last 
                                      > b.attributes.last; }GPA_SORT = 
                                    function(a,b){
                                    return parseFloat(a.attributes.gpa) 
                                      < parseFloat(b.attributes.gpa); } Each is designed to specifically pin point 
                                  a particular property of the XML nodes from 
                                  which to base the array sort from. Now we can 
                                  sort the students_array and pass it in to the 
                                  PopulateLists function to create a sorted version 
                                  of the student listing. To handle that we can 
                                  create the following function: 
                                  var current_sort;SortListBy 
                                    = function(sortType){
                                    if (current_sort 
                                      == sortType){
                                      students_array.reverse(); }else{
                                      students_array.sort(sortType); }current_sort 
                                      = sortType;PopulateLists(students_array); } SortListBy takes a sortType, which is actually 
                                  a sort function, and sorts students_array based 
                                  on that. You can see a variable current_sort 
                                  being used to keep track of which sort was used 
                                  last. This will allow us to reverse the listing 
                                  if a user attempts to use the same sort more 
                                  than one time in a row. Following the sorting 
                                  (or reversing) PopulateLists is called to update 
                                  the text fields with the newly sorted array. With that defined, simply add button actions 
                                  to the column heading buttons specifying the 
                                  correct sort type for each and your set. 
                                  first_btn.onRelease 
                                    = function(){
                                    SortListBy(FIRST_SORT); }last_btn.onRelease 
                                    = function(){
                                    SortListBy(LAST_SORT); }gpa_btn.onRelease 
                                    = function(){
                                    SortListBy(GPA_SORT); } In an effort show that the XML has not been 
                                  altered, the restore button was added to reset 
                                  the students_array back to the grade element's 
                                  current childNodes array. When PopulateLists 
                                  is called with the new definition of students_array, 
                                  you can see the sorting has returned to its 
                                  original unsorted order. 
                                  restore_btn.onRelease 
                                    = function(){
                                    var grades 
                                      = grades_xml.firstChild;students_array 
                                      = grades.childNodes;PopulateLists(students_array); } Use this button and you can see the original 
                                  order unchanged. 
   |