Flash and XML
In the current age of technology, with all of the cool toys and gadgets that are available, all of these things exist for one purpose...to allow us to more easily access information. Today, we are able to acquire information more quickly and easily than we has ever been possible in the past. Largely, this has to do with the internet and the fact that you can access information anywhere in the world from anywhere else in the world in literally the blink of an eye.
So we all know that the information is there, waiting for us to access it. The challenge we as developers face is how to get that information to the user. Up to this point, the information has largely been sitting in static HTML pages, just waiting to be read. The problem with this is that there is more work involved in changing or updating that information as the editor has to know HTML, CSS, etc. So recently, more and more information has moved from static pages to being stored in some "data repository". The most common is the relational database. The great thing about this is that the data is kept seperate from the layout, so you can change the data without having to deal with design issues. All you need is to have a server-side scripting environment (i.e., ColdFusion, ASP, PHP, CGI, etc.) to extract the information from the database and display it for the user in HTML format. This is a wonderful system, however, since each relational database management system (
menuXml = new XML();
menuXml.ignoreWhite = true;
menuXml.onLoad = function(success) {
if (success) {
menuItem = this.firstChild.childNodes;
for (var i=0; i<menuItem.length; i++) {
item = _root.attachMovie("itemClip", "itemClip" + i, i);
item._x = 0;
item._y = 20*i;
item.itemLabel.text = menuItem[i].attributes.name;
item.myUrl = menuItem[i].attributes.url;
item.onRelease = function() {
getURL(this.myUrl,"_blank");
}
}
}
}
menuXml.load("myMenu.xml");
That's it! Now test your movie (making sure that your fla/swf file is in the same location as your xml file in this case) and viola, it should work. This is the bare minimum code you need to make this work.

Now let's go through the code line by line to see exactly what is happening (again, remember that this code is written in and for Flash MX, and all parts of it will not work in Flash 5).
menuXml = new XML();
This line creates a new instance of the XML object and attaches the name "menuXml" to it. After this, if you want to refer to your XML object, you can just refer to the instance name you set. You HAVE to do this if you want to work with XML in Flash.
menuXml.ignoreWhite = true;
Next, we use the "ignoreWhite" property of the XML object and give it a value of true. This tells Flash to ignore the whitespace in your XML document (see discussion on white space above). This property is only available in Flash player 5r41 or higher.
menuXml.load("myMenu.xml");
Skipping right down to the bottom for now, we use the "load" method of the XML object which accepts one parameter - the path to the XML file you want to load. Since the XML file is located in the same directory as our fla/swf file, we just have to tell it the filename.
Now we come to the bulk of the code...the part that actually does stuff with the XML information once it has been loaded and parsed in Flash. Again, let's break it down line by line:
menuXml.onLoad = function(success) {
The XML object has 2 event handlers associated with it: onData and onLoad.
- "onData" executes when the XML data has finished loading, but has not been parsed yet. Sometimes you may want to use the raw XML data before it has been parsed (particularly in Flash 5, where the parsing was slow), however, in most cases, you would use the "onLoad" handler.
- "onLoad" executes when the XML data has finished loading and has been parsed by Flash's XML parser. This is the event we will need to capture.
The "onLoad" handler is an empty function. Basically, that means that when the "onLoad" event occurs, by default, nothing will happen, unless you tell it to do something. The way you tell it to "do something" is by assigning a callback handler to it. The callback handler is just a function that you write that contains the code you want to execute once that particular event occurs. You can assign a callback handler (function) in one of 2 ways.
If you are only going to use the function once, you can just assign it as in the example above (using an unnamed function).
menuXml.onLoad = function(success) {stuff goes here;}
If you want to reuse the function, you will want to create a named function and assign that function to the handler. Notice here that when assigning the callback handler, we write "myCallback" instead of "myCallback()" because we are not executing the function with this line of code, we are just assigning the function to the "onLoad" handler.
function myCallback(success) { stuff goes here; } menuXml.onLoad = myCallback;
Now, back to our example. You may have noticed that the callback function contained a parameter called "success". This is a parameter that is set to either "true" or "false" depending on whether the XML was loaded and parsed successfully. This is handy because now we can test the value of the "success" parameter and either do what you want with the information (if it is available), or tell the user that the XML did not load successfully. We do that in our next line:
if (success) {
This line says to only execute the following code if "success". To put it another way, this is exactly the same as saying "if (success == true);" but we save ourselves a little typing. Next, we begin to extract the information...
menuItem = this.firstChild.childNodes;
First, I need to find my way through the XML object structure that the Flash player has so kindly parsed my data into. If you look back at the XML structure we created, you see that we have as our root element "<myMenu>", and that element contains 4 "child" elements called "<myItem>". Any element that is nested inside another element is considered a "child of that "parent" element. The nested elements also have a "sibling"relationship to each other. These are terms that are commonly used to describe the relationship between elements in XML, and is used by Flash as well.
So the important elements (which I will refer to as nodes from here on in) are the "<myItem>" nodes. These nodes contain the actual information I need to build my menu. To access these nodes, I say "this.firstChild.childNodes". There are 3 parts to the path stated here:
- "this" refers to the XML object instance "menuXml". That is because this code is located in the function assigned to the "menuXml.onLoad" handler.
- "firstChild" is a property that refers to the first child node of the root node in this example. In this case it is "<myMenu>".
- "childNodes" returns an array that contains all of the child nodes of a particular node. In this case, the array will contain all of the four "<myItem>" nodes.
We take this information and store it in the variable "menuItem" so we can reference it later on without having to type "this.firstChild.childNodes" over and over again.
for (var i=0; i<menuItem.length; i++) {
In order to extract all of the information we need, and then build the menu, we have to be able to loop through and extract information from each of the "<myItem>" nodes (i.e., the "name" and "url" data). You can do this several ways, but in our example, we'll use a "for" loop. This type of loop consists of 3 parts:
- Initialization (var i=0) - This sets the initial value of the "iteration variable".
- Condition (i < menuItem.length) - This tells the loop to continue until this condition is no longer true. "menuItem.length" returns the number of items in the array (remember that this array contains the number of "<myItem>" nodes in the XML object).
- Increment/Decrement (i++) - This tells the iteration variable to increase by 1 every time through the loop.
So this loop will allow us to extract information beginning with the first element in the array (remember arrays begin at index 0) to the last element in the array.
item = _root.attachMovie("itemClip", "itemClip" + i, i);
With each node (array item), we first dynamically attach the movie clip we created to the stage using the "attachMovie" method and store it in a variable called "item". Again, this allows us to reference the attached movie clip without having to write the path to that clip every time. The "attachMovie" method takes 3 parameters:
- Identifier name ("itemClip") - This is the name we set in the "Identifier" field when we set the movie clip to "Export for Actionscript".
- Instance name ("itemClip" + i) - This is the instance name of the movie clip we've attached.
- Depth (i) - This sets the depth (z-index) of the attached clip.
So, for every "<myItem>" node in the XML file, a new movieclip is attached to the stage.
item._x = 0;
This sets the "_x" property (position of the clip on the stage in x direction) to 0, which is the very left edge of the stage.
item._y = 20*i;
This sets the "_y" property (position of the clip on the stage in y direction) to a different value depending on what the value of "i" is. By multiplying "i" by 20, the menu items will cascade vertically, and will be offset 20 pixels from the previous item.
item.itemLabel.text = menuItem[i].attributes.name;
Next, we want to extract the "name" attribute from the "<myItem>" node to display it in our dynamic text field. We can do that by using "menuItem[i]" to find the current node (array item). So in our example, menuItem[0] would represent the first "<myItem>" node. We then use the attributes property, and the "name" attribute specifically to extract that information.
After extracting the information, we have to display it in the text field somehow. In Flash MX, text fields are treated as objects and can now have instance names (whereas in Flash 5 you had to use a variable name). To insert text into the text field, we will use the "text" property of the text field ("itemLabel" was the instance name). And since the text field is inside of the movie clip, we use the path "item.itemLabel.text".
item.myUrl = menuItem[i].attributes.url;
The other piece of information we need is contained in the "url" attribute. We can access this the exact same way as the "name" attribute, just replacing "url" for "name". Then, we are just going to store this for now in a variable I called "myUrl" which is located in the movie clip.
The last thing that needs to be done is to create the action so that when the user presses one of the menu items, a new browser window will open with the url we've set. However, notice that we have not created a button symbol yet (and we will NOT be creating one at all!). In Flash MX, movie clips are equipped with pretty much all of the same event handlers as buttons have. Not only that, but the event handlers do not have to be attached to the specific movie clip (or button) in Flash MX. You can dynamically set an event handler in much the same way as we did with "onLoad" earlier...by using a callback handler.
item.onRelease = function() {
Here, we'll use the "onRelease" handler of the "item" movie clip that we just attached. We assign this to an unnamed function. This is great because by placing this code here, we no longer have to hunt around in our Flash movie to find the appropriate button or movie clip. We just have to look in frame 1 of the root timeline!
getURL(this.myUrl,"_blank");
The final thing we have to do is tell Flash what to do when the "onRelease" event occurs. This is a simple "getURL" command that tells Flash to open the url "this.myUrl". This is just calling on the variable "myUrl" that we created earlier which contains information from the "url" attribute of our XML file.
Then, after we end the appropriate functions, for loops, and if statements using "{", we're done. This menu is generated dynamically via the XML data. Don't believe me? Export the swf file, then go back to your XML file and add or remove one of the "<myItem>" nodes. Then, reopen your swf file and see what happens :)
Obviously, this is a very simple example. However, you can expand this concept to create very elaborate XML driven Flash front-ends. Here are a couple of examples:
This is a Flash interface that extracts information from a publicly accessible news feed created by Macromedia and allows you to sort it by several different categories, all of which are described in the XML document.
A Flash interface that reads news feeds in RSS format (an XML implementation). This brings in news feeds that have been syndicated from various sources (mostly blogs) and provides a Flash front end to these news items.
Downloads & More
discuss this topic to forum
