Skip to main content

Home

Daniel C. Fergus

Artist & Educator

VCB-331 Rich Media 1

XML and Flash (AS3)—an Introduction

Introduction

XML stands for Extensible Markup Language, which is a simple tag-based language that is used to store data. XML is very similar to XHTML in that they both use tags to indicate a hierarchical structure of information. However, unlike XTHML tags which are pre-determined, XML tags can be created and defined by the writer. This makes XML a far more flexible language.

Many programming languages can make use of data stored in XML files, including Javascript and ActionScript. This allows us to create self-contained Flash files that are able to read data from and outside source file at run time and use it dynamically. When changes need to be made to the data, the XML file is modified; the Flash file can does not have to be touched.

XML page structure

XML documents look a lot like HTML documents, but they don't need all the header information, DOCTYPES, meta tags, etc. Here's a sample XML file:

<?xml version="1.0" encoding="ISO-8859-1"?>  
    <myFriends>
        <friend>
            <name>Fred</name>
        </friend>
        <friend>
            <name>Barney</name>
        </friend>
        <friend>
            <name>Wilma</name>
        </friend>
        <friend>
            <name>Betty</name>
        </friend>  
    </myFriends> 

In XML speak, pieces of data described by tags are known as elements or nodes. The outermost tag (myFriends) is known as the root node. Enclosed tags are called children (so <friend> is a child of <myFriends> and <name> is a child of <friend>).

The bits of text between the name tags (Fred, Barney, etc.) are known as text nodes. These are actually optional; you can create an XML file that is all tags with nothing between them.

Another way data can be stored in an XML file is to use attributes. Consider the following XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
    <myFriends>
        <friend name="Fred" />
        <friend name="Barney" />
        <friend name="Wilma" />
        <friend name="Betty" />  
    </myFriends> 

This version contains the same information as the first, but instead of using text nodes to hold the names, it uses attributes within the tags. The advantage is obvious—less typing! But it also creates a somewhat less flexible structure. There are those that advocate for one method over the other; I don't really care as long as it works. I usually use a mix of both.

Note that as in XHTML, all tags must be closed. Any non-container tags must have a slash at the end: <friend />

Flash and XML

Let's see how AS3 can be used to access XML data.

  1. Below is some sample XML code. Copy it and paste it into a plain text document (or you could create a new XML file with Dreamweaver. However, if you do that make sure you don't duplicate the declaration (the first line)):
    <?xml version="1.0" encoding="ISO-8859-1"?>    
        <TVGuide>
            <Channel id="PBS">
                <!--<Day id="Thursday">-->
                <Program id="This Old House Hour" starttime="7:00">The gang fixes up a house you couldn't 
    afford in your wildest dreams</Program> <Program id="Antiques Road Show" starttime="8:00">People wait in line all day with their junk</Program> <Program id="The New Red Green Show" starttime="9:00">Red and the boys do dumb guy things </Program> <!--</Day>--> </Channel> <Channel id="NBC"> <!--<Day id="Thursday">--> <Program id="Community" starttime="7:00">Chevy Chase tries to revive his career</Program> <Program id="Parks and Recreation" starttime="7:30">Amy Pohler and Rashida Jones are the bomb</Program> <Program id="The Office" starttime="8:00" >How many Americans know that this was actually a British show first?</Program> <Program id="30 Rock" starttime="8:30">Tina Fey and Alec Baldwin rock! (no pun intended) </Program> <Program id="The Jay Leno Show" starttime="9:00">*Yawn*</Program> <!--</Day>--> </Channel> <Channel id="CBS"> <!--<Day id="Thursday">--> <Program id="Survivor:Samoa" starttime="7:00">Barely dressed idiots play 'Beat the Clock' on the beach</Program> <Program id="CSI:Crime Scene Investigation" starttime="8:00">Holy crap another CSI show? Real original CBS!</Program> <Program id="The Mentalist" starttime="9:00">aka 'Lie to Me' or 'Psych'</Program> <!--</Day>--> </Channel> </TVGuide>
    You'll note that some of the tags are commented out. Don't worry, I did that on purpose; we'll get rid of those comments later (but leave them there for now).
  2. Save this as TVGuide.xml.
  3. Open a new Flash file and save it as myTVGuide.fla. Save it in the same volume (folder) as the XML file.
  4. Open the Actions window. Type the following:
    var myXML:XML;    
    var myLoader:URLLoader = new URLLoader();        
    myLoader.load(new URLRequest("TVGuide.xml"));  
    In order to use an XML file we need an instance of the XML class (which we've called "myXML"). Since it's an external file, we need to create an instance of the Loader class (we'll call it "myLoader") and a URLRequest class ("myURLRequest"). Note that if your file is named something other than "TVGuide.xml" you'll have to adjust your code accordingly.
  5. Next we need to add a listener:
    myLoader.addEventListener(Event.COMPLETE, processXML);

    It's important that the XML file is entirely loaded before Flash tries to do anything with the data. This line listens for the completion of the load operation, calling the "processXML" function only after the data has finished loading.

  6. Now for the "processXML" function:
    function processXML(myEvent:Event):void { 
        myXML=new XML(myLoader.data);
        trace(myXML.name());    
    }  
    This function takes our XML object ("myXML") and fills it with the loaded data. Then we trace the name of the XML root node to make sure everything is working. Run it; you should see "TVGuide" appear in the Output window.

Reading elements in an XML tree

  1. We'll use a new object, the XMLList class to help us get at specific pieces of data. For example, let's say you wanted to see all of the shows in the PBS element. Add the new bits:
    function processXML(myEvent:Event):void { 
        myXML=new XML(myLoader.data);
        var myShow:XMLList=myXML.Channel[0].children(); 
        trace(myShow);    
    }  
    This creates a variable called "myShow" and assigns it the data found in the first Channel node (remember arrays start counting at zero). By writing "children" it shows us all of the separate Program nodes under Channel 1. (Note the change to the trace command).
  2. Okay, but what if you only want to grab one particular show? Change "children" to "child" and add a number to the parenthesis:
    function processXML(myEvent:Event):void { 
        myXML=new XML(myLoader.data);
        var myShow:XMLList=myXML.Channel[0].child(2); 
        trace(myShow);    
    }  
    Hmmm...it just gave me the text node , the description of the third show on PBS ("Red and the boys do dumb guy things"). What about the name of the show? Well, remember that the name is actually an attribute of the "Program" tag. To get at it we need to rewrite the code to target that attribute. To do this we use the @ sign ("at" for "attribute;" get it?). Since there are several attributes we need to specify which one we want (in this case, the "id" attribute).
  3. Try this variation:
    function processXML(myEvent:Event):void { 
        myXML=new XML(myLoader.data);
        var myShow:XMLList=myXML.Channel[0].child(2).@id; 
        trace(myShow);    
    }  
    This time the name of the show (The New Red Green Show) should have popped up. Cool!
  4. But what if we didn't know which channel PBS was? Let's say we want to know what the first show on NBC is, but we don't know which child it is. If we know the id ("NBC") we can search for it using a simple conditional statement:
    function processXML(myEvent:Event):void { 
        myXML=new XML(myLoader.data);
        var myShow:XMLList=myXML.Channel.(@id == "NBC").child(0).@id; 
        trace(myShow);    
    }  
    This should return Community, the first show on NBC. Note what we did here; instead of listing a specific Channel, we use a conditional (@id == "NBC") to look for the proper id. Once found, we requested it's first child's id.
  5. We can create even more complex searchers. Let's say we wanted to know which show was on at 8:00 on NBC; we don't know if it's the first, second, third, or fiftieth show on the network so we need to search for both network ID and start time ID:
    function processXML(myEvent:Event):void { 
        myXML=new XML(myLoader.data);
        var myShow:XMLList=myXML.Channel.(@id == "NBC").Program.(@starttime == "8:00").@id; 
        trace(myShow);    
    }  
    This will return The Office.
  6. Now let's search for all shows starting at 8 on all of the channels:
    function processXML(myEvent:Event):void { 
        myXML=new XML(myLoader.data);
        var myShow:XMLList=myXML.*.Program.(@starttime == "8:00").@id; 
        trace(myShow);    
    }  
    Replace the "Channel" node and it's conditional with a "wildcard" (universal) symbol (*). This returns all of the 8:00 shows; granted they all run together in the Output window, but we could fix that with a little formatting if we wanted to.

Searching for an attribute at any level

Of course, there are times when this still won't help us. Imagine for a minute that you don't know that there are nodes called "Program," or you are not sure where they are in the hierarchy. Or, let's say someone comes along and adds a few tags to the XML file.

  1. For example, open the XML file and find the commented-out tags. Remove the comments and re-save it. Removing the comments adds a new set of "day" tags to the mix. If you run the Flash file now nothing will appear in the Output. So what to do
  2. Well we could modify the code and add the new node, or, we could remove the asterisk and leave the dots:
    function processXML(myEvent:Event):void { 
        myXML=new XML(myLoader.data);
        var myShow:XMLList=myXML..Program.(@starttime == "8:00").@id; 
        trace(myShow);    
    }  

    The two dots tell the computer to search through all levels of the XML looking for Program nodes with start times of 8:00. The one drawback to this method is the amount of processing power needed to use it. It's best therefore to only use this method when you absolutely have to.

  3. It's also possible to call specific entries in the XMLList by using the array position syntax:
    function processXML(myEvent:Event):void { 
        myXML=new XML(myLoader.data);
       var myShow:XMLList=myXML..Program.(@starttime == "8:00").@id; 
        trace(myShow[2]);    
    }  

    This returns just one of the 8:00 shows (CSI, I believe).

  4. Finally, we can access text nodes in much the same way:
    function processXML(myEvent:Event):void { 
        myXML=new XML(myLoader.data);
       var myShow:XMLList=myXML.Channel.Day.Program; 
        trace(myShow*[4]);    
    }  

    This returns the description of the fifth show in the array (Park and Recreation).

 

decorative thumbnail

All text, images, and multimedia pieces (unless otherwise specified) copyright 2005–2011 Daniel C. Fergus. All rights reserved. No reproduction without permission.