XML Object

 <  Day Day Up  >  

Flash support for XML is manifested through several objects and methods, primarily the XML object. This object loads XML, transforms XML to an ActionScript datatype, and provides methods to manipulate the data. The XML object also provides the ability to send XML to a server. This is particularly useful when submitting data to the server requires secure transmission, as in passwords, or when a server-side script is expecting XML. XML enables us to read and write to a server without any additional data access components (see Chapter 14, "Using Client-Side Data Integration," for more information).

Reading an XML Document

XML provides a structured view of data that can be read by a Flash application on the Internet. The XML object has a method to load XML documents from a server. The Flash Player supports standard XML and has built-in parsing capability. Note that the XML document has to be well- formed for accurate data parsing.

In this part of the chapter, we build a Flash navigation system for a web application using an XML file to provide us with the menu item names and links. In this simple example, we do the following:

  • Load an XML file

  • Parse the XML

  • Use the data to populate attributes of a Flash menu

The menu will consist of a movie clip that exists in the Library, a custom XML object that will load and parse the data, and a method to populate the menu. Figure 12.3 shows the final menu. The menu is created based on the number of elements in the XML document.

Figure 12.3. XML-driven menu.

graphics/12fig03.gif

The XML document used to create this menu is shown in Listing 12.7. The document root is the first node of the XML content. Notice the attributes of each root-child node. Each node contains a " name " and an "action" attribute. These will be used to populate menu items as they are created.

Listing 12.7. Contents of XMLMenu.xml
 <menu>// document  root  <item name="Home" action="/home.htm"/>// child node with       attributes       <item name="Products" action=http://www.amazon.com/product.htm&id=87/>       <item name="Solutions" action="/solution.htm"/>       <item name="Customers" action="/customers.htm"/>       <item name="About Us" action="/aboutUs.htm"/> </menu> 
Loading XML Data

The first step to creating our XML-driven menu is to load the XML document into Flash. Using the XML Object constructor, create an instance of the XML object. Listing 12.8 shows the correct syntax for creating an instance of the XML class.

Listing 12.8. Creating an Instance of the XML Class
 var xmlInstance = new XML(); xmlInstance.load("http://www.mySite.com/XMLMenu.xml"); 

A better choice would be to create a custom class that inherits from the XML object. This enables us to encapsulate the file loading, parsing, and data manipulation in one class. Listing 12.9 creates a custom class named XMLMenu . This class is a subclass of the XML object. Notice that the constructor calls super() . In Chapter 5, "The Meek Shall Inherit the Earth," we learned that calling super() in the constructor of a class will call the constructor of its direct ancestor . In this case, it is equivalent to new XML() .

Listing 12.9. Creating a Custom XML Class
 class XMLMenu extends XML{ public function XMLMenu(XMLFileName:String) {              super();              this.load(XMLFileName);       } } 

The custom class constructor will load the XML file when the instance is created and passed a file name. Remember that when a subclass is created, the new class inherits all the properties and methods of the ancestor, in this case, the XML object. Therefore, we can call the load method of our custom class just as we would with the native XML class shown in Listing 12.8.

The instance is created in the host file that uses the XML content. In the case of the XML menu, that will be the host FLA file, XMLMenu.fla. Figure 12.4 shows the new instantiation code in the first frame of the main timeline of XMLMenu.fla.

Figure 12.4. Creating an instance of a custom XML class.

graphics/12fig04.gif

The next step is to parse the data. Because there might be some latency between the file request and the file load, the XML object has an event that is fired when the file has finished loading. onLoad() is a method added to the custom class to capture file load completion. Listing 12.10 includes the onLoad() method that is executed when the file has been completely loaded into the object. In this method, we can parse the data and notify any interested objects when the data is loaded. This is also referred to as a callback method. Notice that the onLoad method contains a Boolean argument. If the file loaded successfully, the argument is true; otherwise , it is false. This allows for file access error handling.

Listing 12.10. Adding the onLoad() Method to the Custom XML Class
 class XMLMenu extends XML{ public function XMLMenu(XMLFileName:String) {       super();       this.load(XMLFileName); } = public function onLoad(success:Boolean){       if (success) {             trace("file loaded");             //parse data if needed             //notify display objects that data has loaded       }else{             trace("FILE NOT LOADED");             //handle file load error       } } } 
Parsing the Data

How you parse the data is dependent on what you are going to do with the data. In the case of the Flash menu, the attributes needed to build the menu are the name and action for each menu item. As we traverse the XML document, an array can be built and passed to the main timeline to build the menu.

N OTE

In Macromedia Flash MX 2004, there are components that can bind directly to an ActionScript XML instance. Chapter 13, "Web Services," covers direct data binding. In the example in this chapter, we manually parse the XML data.


In Flash, XML objects have a hierarchical tree structure. There are many methods and properties we can use to traverse the tree structure and extract the data. All XML objects begin with a root node. The root node can contain information called metadata, which describes the contents of the XML document. Each node has a reference to its data as child nodes. Child nodes are accessed using the childNodes property that returns a collection of nodes, as shown in Figures 12.5 and 12.6. Note that XML trees can be very deep. Each node can have children, and these child nodes can have children, and so on.

Figure 12.5. XML child nodes.

graphics/12fig05.gif

Figure 12.6. XML tree nodes.

graphics/12fig06.gif

The XML class provides methods and properties to facilitate traversing data both up and down the XML tree. It does this by providing both built-in references to neighboring elements and general tree structures. Table 12.1 enumerates the properties and methods that can be used while parsing the XML object.

Table 12.1. Properties, Methods, and Return Types of the XML Object

P ROPERTY AND M ETHODS

R ETURN T YPES

Attributes

Returns an associative array containing all of the attributes of the specified node

ChildNodes

Read-only; returns an array containing references to the child nodes of the specified node

FirstChild

Read-only; references the first child in the list for the specified node

hasChildNodes()

Returns true if the specified node has child nodes; otherwise, returns false

LastChild

References the last child in the list for the specified node

nextSibling

Read-only; references the next sibling in the parent node's child list

NodeName

The node name of an XML object

NodeType

The type of the specified node (XML element “type = 1, text node “type = 3)

NodeValue

The text of the specified node if the node is a text node

ParentNode

Read-only; references the parent node of the specified node

previousSibling

Read-only; references the previous sibling in the parent node's child list

RemoveNode()

Removes the specified node from its parent

toString()

Converts the specified node and any children to XML text

Listing 12.11 demonstrates the onLoad() method parsing the XML content. The onLoad() method employs XML properties and methods to parse the data. Notice that in the onLoad() method, the childNodes property is accessed twice. The first access points to the first node in the object. In this case, the first node is the root of the document labeled "menu," as seen in Listing 12.8.

Listing 12.11. onLoad() Method Parsing the XML Content
 class XMLMenu extends XML{       public var menuItems:Array//;//create array to pass back       public var parent:Object//;// create reference to calling object       public function XMLMenu(XMLFileName:String, parent:Object) { super();             this.parent = parent;             this.menuItems = new Array();//// instantiate menu array             this.load(XMLFileName);       }    public function onLoad(success){       if (success) {             var rootList:Object = this.childNodes//;//access root nodes             var itemList:Object = rootList.childNodes//;//access child nodes             var itemListLen:Number = itemList.length;             for (var i = 0; i < itemListLen; i++) {                var itemObj:Object = {};                itemObj.name = itemList[i].attributes.name;//// attributes                itemObj.action = itemList[i].attributes.action; //// attributes                this.menuItems.push(itemObj); //// populate menu array             }             //send menu array back to the calling fla       } else {             trace("Menu content failed to load");       }    } } 
Populating the Menu with the Parsed XML Data

After the data is parsed into suitable ActionScript datatypes (which, in this case, is an array), the menu can be populated . The calling script in the Flash file will be notified when the data has been parsed. To facilitate communication from the host to the XML object, a reference to the parent object was passed in at the time of instantiation. This enables us to call back to the parent when the data is ready.

In Listing 12.12, the callback to the Flash file is included. Using the parent reference, a callback to the parent's loadMenu() method is made, passing back the menu items derived from the XML content.

Listing 12.12. onLoad() Method Returning Data to Parent
 class XMLMenu extends XML{       public var menuItems:Array;// create array to pass back       public var parent:Object;// create reference to calling object       public function XMLMenu(XMLFileName:String, parent:Object) {             super();             this.parent = parent;             this.menuItems = new Array();// instantiate menu array             this.load(XMLFileName);      }    public function onLoad(success){       if (success) {             var rootList:Object = this.childNodes;//access root nodes             var itemList:Object = rootList.childNodes;//child nodes             var itemListLen:Number = itemList.length;             for (var i = 0; i < itemListLen; i++) {                var itemObj:Object = {};                itemObj.name = itemList[i].attributes.name;// attributes                itemObj.action = itemList[i].attributes.action;// attributes                this.menuItems.push(itemObj); // populate menu array             }             parent.loadMenu(this.menuItems);       } else {             trace("Menu content failed to load");       }    } } 

In the parent object, flashMenu.fla, the loadMenu() method exists and accepts the menuItems array from the custom XML object. Figure 12.7 shows the loadMenu() method that dynamically attaches menu items and populates their values based on the menuItems array.

Figure 12.7. loadMenu() building first-level menu.

graphics/12fig07.jpg

The menu we have built so far has a flat hierarchy, but most menus require additional level of depth, in the form of submenus. Because the structure of XML documents is hierarchical, or tree-like, it is suited for multi-level menus . To add submenus to our XML menu, we will add additional entries in the XMLMenu.xml file. Listing 12.13 shows the new XML that we will use to populate the menu.

Listing 12.13. XMLMenu.as with Submenu Entries
 <menu >       <item name="Home" action="/home.htm">       </item>       <item name="Products" action="none">           <item name="Toys" action="/toys.htm"></item>   sub menu  <item name="Electronics" action="/electronics.htm"></item>   sub menu  <item name="Books" action="/books.htm"></item>   sub menu  <item name="Pets" action="/pets.htm"></item>   sub menu  </item>       <item name="Solutions" action="/solution.htm">       </item>       <item name="Customers" action="/customers.htm">             <item name="FAO Schwarz" action="/toys.htm"></item>             <item name="Best Buy" action="/electronics.htm"></item>             <item name="Home Depot" action="/books.htm"></item>             <item name="PetCo" action="/pets.htm"></item>             <item name="TVGuide" action="/pets.htm"></item>             <item name="Macromedia" action="/pets.htm"></item>       </item>       <item name="About Us" action="/aboutUs.htm">             <item name="Corporate" action="/Corporate.htm"></item>             <item name="Opportunities" action="/Opportunities.htm">             </item>             <item name="Contact Us" action="/Contact.htm"></item>       </item> </menu> 

Using what we already know about traversing an XML document, we will load and parse the document by stepping down into the submenu level of the XML. Listing 12.14 shows the new onLoad() method of the XMLMenu.as. The onLoad() method will now build an array called sub[] that will hold the attributes of the submenus, if they exist.

Listing 12.14. onLoad() Method Parsing Submenu Items
 public function onLoad(success){       if (success) {             var itemList:Object = this.childNodes[0].childNodes;       var itemListLen:Number = itemList.length;             for (var i = 0; i < itemListLen; i++) {               var subList:Object = itemList[i].childNodes;               var subItemLen:Number = subList.length;               var itemObj:Object = {};               itemObj.sub = []; // create sub menu array               itemObj.name = itemList[i].attributes.name;               itemObj.action = itemList[i].attributes.action;               //iterate through current items child nodes               for (var j = 0; j < subItemLen; j++) {                  var subItemObj:Object = {};  // create sub menu object  subItemObj.name = subList[j].attributes.name;                  subItemObj.action = subList[j].attributes.action;                  itemObj.sub.push(subItemObj);  // populate sub menu   array  }                  this.menuItems.push(itemObj);             }                  parent.loadMenu(this.menuItems);       } else {              trace("Menu content failed to load");       } } 

We will also have to modify the menuItem.as file to paint the submenu when it exists. Listing 12.15 show the new populateMenu() method. If the sub[] is populated, the menu item will create a submenu. Note that this could also be done using a recursive function, allowing a menu to be of any depth, but for the sake of clarity, we have chosen a more verbose coding style, thus limiting the menu to two levels.

Listing 12.15. populateMenuItem() Creating a Submenu
 public function populateItem(menuItem:Object) {       if (menuItem.sub.length > 0){  //sub menu exists?  this.subMenuItems = menuItem.sub;             this.subMenu = true;             this.createEmptyMovieClip("sub_mc", 100,{_x:0,_y:0});             var xmlObj = this.subMenuItems;             var subMenuItemCount:Number = xmlObj.length;             var itemX:Number =0;             var itemY:Number = this._height;             var rowH:Number = this._height;             for(var i=0; i<subMenuItemCount; i++){ //  populate sub   menu  this.sub_mc.attachMovie("MenuItem","subMenu"+i, I);                   this.sub_mc["subMenu"+I]._x = itemX;                   this.sub_mc["subMenu"+I]._y = itemY;                   this.sub_mc["subMenu"+i].populateItem(xmlObj[i]);                   itemY += rowH;             }             this.sub_mc._visible = false;       }       this.menuItem = menuItem;       this.label_txt.text = menuItem.name;       this.link_str =  menuItem.action; } 

The new menu now has submenus, and the menu content can be changed at any time without changing the Flash files. By simply changing the XML files, a completely different menu can be generated. Figure 12.8 shows the new menu with the expanded submenu.

Figure 12.8. XML-driven menu with submenu.

graphics/12fig08.gif

Sending an XML Document

There are several ways to send data from a Flash movie to a server, and each has advantages and disadvantages. Using the getURL() method of the MovieClip object, we can append data to the URL. Using the query string on the end of the URL has length limitations and can become very unruly with large datasets. It also has security limitations.

Flash Remoting and Web Services also enable us to pass data back to a server from Flash. However, these involve server-side technologies and require an investment in software and resources. Using XML documents to pass data from Flash to a server is cheap and can provide a level of data security with minimal investment in software and IT resources. Most application servers, such as ASP.NET and ColdFusion, can parse XML on the server. Many databases can also parse and insert XML data directly into tables.

The XML object has methods to support the creation and packaging of XML data to be sent to a server. Table 12.2 enumerates the methods available to create and manipulate an XML object for sending data to a server.

Table 12.2. XML Methods for Creating and Sending Data

M ETHOD

D ESCRIPTION

XML.addRequestHeader()

Adds or changes Hypertext Transfer Protocol (HTTP) headers for power-on self test ( POST) operations

XML.appendChild()

Appends a node to the end of the specified object's child list

XML.cneNode()

Clones the specified node and, optionally , recursively clones all children

XML.createElement()

Creates a new XML element

XML.createTextNode()

Creates a new XML text node

XML.getBytesLoaded()

Returns the number of bytes loaded for the specified XML document

XML.getBytesTotal()

Returns the size of the XML document, in bytes

XML.insertBefore()

Inserts a node in front of an existing node in the specified node's child list

XML.load()

Loads a document (specified by the XML object) from a URL

XML.removeNode()

Removes the specified node from its parent

XML.send()

Sends the specified XML object to a URL

XML.sendAndLoad()

Sends the specified XML object to a URL and loads the server response into another XML object

send() Method

The send() method enables us to send XML data to a URL. It is a method of the XML object and takes a single argument, a URL. Listing 12.16 shows an example of the send() method in action. This method is used when no return response is required. For example, a site that is doing a public poll or a survey might want the user to answer a few questions and submit the answers. A simple way to do this in Flash is to create an XML object to hold the answers and then submit them to a server using the XML.send() method. Listing 12.16 lists an example of building the XML object and calling the send method.

Listing 12.16. XMLSendSurvey ”an XML Subclass
 class XMLSendSurvey extends XML{       public function XMLSendSurvey() {             super();       }       public function sendSurveyResults(surveyAnswers:Array){             for (var i=0; i<surveyAnswers.length; i++){                   //Create elements for each question                   var newElement = this.createElement("item");                   newElement.attributes.answer = surveyAnswers[i].answer;                   newElement.attributes.question = surveyAnswers[i].question;                   //append element for each question                   this.appendChild(newElement);             }             //send the XML             this.send("http://www.mySite.com/survey.cfm" );       } } 

The XML being sent to the server would contain questions and answers similar to Listing 12.17.

Listing 12.17. Survey Data XML
 <survey>       <item question="1" answer="yes" />       <item question="2" answer="no" />       <item question="3" answer="maybe" /> </survey> 
sendAndLoad() Method

The sendAndLoad() method enables us to send XML data to a URL. It also enables us to identify a client XML object that will receive any returning data. The object receiving the data is an XML object created through the XML constructor method. Listing 12.18 is an example of a sendAndLoad() method call for a registration system that returns confirmation to the client. Notice that we are using the same XML object to send the registration as we are to receive the response from the server.

Listing 12.18. sendAndLoad() for the Registration System
 class XMLRegistration extends XML{       public function XMLRegistration() {             super();       }       public function sendRegistration(formData:Array){             for (var i=0; i<surveyAnswers.length; i++){                   var newElement = this.createElement("question"+i);                   newElement.attributes.label = formData[i].label;                   newElement.attributes.value = formData[i].value;                   this.appendChild(newElement);             }             //Send the registration to the server,             //pass a reference to 'this'. this.onLoad()-receives the reply             this.sendAndLoad("http://www.mySite.com/registration.cfm",             this);       }       function onLoad(success){             if (success){                   //parse the reply and notify the user             }       } } 

The sendAndLoad() method encodes the specified XML object into an XML document, sends it to the specified URL using the POST method, downloads the server's response, and then loads that response into the targetXMLobject specified in the parameters. The server response is loaded in the same manner used by the load() method.

When sendAndLoad() is executed, the XML object property loaded is set to false . When the XML data finishes downloading, the loaded property is set to true , and the onLoad() method is invoked. The XML data is not parsed until it is completely downloaded. If the receiving XML object previously contained any XML trees, they are discarded.

Sandbox Restrictions

For SWF files running in a version of the Player earlier than Flash Player 7, the receiving URL must be in the same superdomain as the SWF file that is issuing this call. For example, an SWF file at www.Yahoo.com can load variables from an SWF file at products.Yahoo.com because both files are in the same superdomain of Yahoo.com .

If the SWF is running in Flash Player 7 or later, the receiving URL must be in exactly the same domain. For example, an SWF file at www.Yahoo.com can load variables only from SWF files that are located at www.Yahoo.com . If you want to load variables from a different domain, you can place a cross-domain policy file on the server hosting the SWF file that is being accessed. For more information, see Chapter 13.

 <  Day Day Up  >  


Object-Oriented Programming with ActionScript 2.0
Object-Oriented Programming with ActionScript 2.0
ISBN: 0735713804
EAN: 2147483647
Year: 2004
Pages: 162

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