AS3 How to and Tips > Loading and Processing External XML Files

One of the greatest new features of ActionScript 3 is how easy it is to work with XML data. In many of our tutorials, we used external XML content. In XML-Driven 3D Spinning Menu and Photo Gallery in Flash CS4, for example, we stored data about thumbnails and images to load in an external XML file. That means that in order to replace the pictures and customize the gallery one needs to change the XML file only, without recompiling the Flash movie. Given that an XML file is in essence a text file, editing XML is a breeze. In this How-To, we show how to load and procees content of an external XML file.

Download

Download all the well-commented source files for this How-To in the following compressed folder.

The Content of the External XML File

One of the files that you will find in the 'zip' package is rectdata.xml. This is the external XML file loaded at runtime. The file contains information about the colored rectangles on the black board. The rectangles are drawn based on the information in the XML file. You can open rectdata.xml in any plain text editor, for example in Notepad, and see its content. It is necessary to see the XML file to understand the code in the loadxml.fla file corresponding to the applet above. (If you click the button in the applet, you can see the content of the file displayed in the text field.)

<rectangles>

<rec>

<dimensions w="50" h="80" />

<startpoint ptx="30" pty="20" />

<look>

<fillhex>0x990099</fillhex>

<strokehex>0x006600</strokehex>

<strokethick>4</strokethick>

</look>

</rec>

<rec>

<dimensions w="90" h="50" />

<startpoint ptx="40" pty="200" />

<look>

<fillhex>0xCCCC00</fillhex>

<strokehex>0x990000</strokehex>

<strokethick>3</strokethick>

</look>

</rec>

<rec>

<dimensions w="60" h="60" />

<startpoint ptx="150" pty="100" />

<look>

<fillhex>0x3333FF</fillhex>

<strokehex>0xCCCC00</strokehex>

<strokethick>1</strokethick>

</look>

</rec>

</rectangles>

 

You can see the characteristic, tree-like structure of an XML file. The names of the tags are chosen arbitrarily. In general, you try to make the names of tags in your XML files descriptive. Some of the names we chose sound funny as we were trying to avoid AS3 keywords (like rect or rectangle). Although, it wouldn't have mattered if they were keywords. We just didn't want the names to display in blue in the loadxml.fla file as that could appear confusing.

The Code in the 'fla' File

/*
We create a Sprite, board, and add it as a child of the MainTimeline. In board we will draw the black rectangle before the XML file loads. We create a Shape, drawings, a child of board. In 'drawings' we will draw colored rectangles based on the data in the XML file that we will load.
*/

var board:Sprite = new Sprite();

this.addChild(board);

board.x = 305;

board.y = 45;

var drawings:Shape=new Shape();

board.addChild(drawings);

/*
To load an XML file at runtime, we create an instance of the URLLoader class and attach listeners to it to listen to events related to loading.
*/

var ldr:URLLoader = new URLLoader();

ldr.addEventListener(Event.COMPLETE, loadComplete);

ldr.addEventListener(IOErrorEvent.IO_ERROR, loadError);

/*
We will store the content of the loaded XML file in the variable xmlContent.
*/

var xmlContent:XML;

/*
We call a function 'drawBoard' (defined at the end of the script) that draws the black rectangle.
*/

drawBoard();

/*
Besides some static text, we created on the stage a button with instance name 'btnShowFile' and a dynamic text field, 'txtOutput'. We also placed on the stage an instance of the component UIScrollBar. We targeted it at txtOutput, and gave it an instance name 'verScrollBar'.
*/

/*
The button, btnShowFile, when clicked will display the content of the loaded XML file in the dynamic text field, txtOutput. We make the button invisible until the XML file finishes loading. We make the scroll bar invisible until the user clicks on the button.
*/

verScrollBar.visible=false;

btnShowFile.visible=false;

/*
We call the 'load' method on our URLLoader instance. We pass to the method an instance of the URLRequest that points to the file to be loaded. In our case, the file, rectdata.xml, is located in the same directory as the swf and html files corresponding to this fla file. In general, you pass to URLRequest a String containing the address of the XMl file on your server. (Loading from remote domains may cause security errors that we do not discuss here.)
*/

ldr.load(new URLRequest("rectdata.xml"));

txtOutput.text="Loading an XML file...";

/*
When loading is complete, we store the content of the loaded XML file in the variable xmlContent. The datatype of ldr.data is String. In order to convert the String to an XML object, we apply the XML class' constructor: xmlContent = new XML(ldr.data). Instead, we could use: xmlContent = XML(ldr.data). In the latter case, the global function XML() is applied to ldr.data. The global function XML() converts the String to an XML object. Within 'loadComplete', we call the function 'createDrawings' that processes the XML and draws the colored rectangles.
*/

function loadComplete(e:Event):void {

xmlContent = new XML(ldr.data);

txtOutput.text="An external XML file, rectdata.xml, was loaded as the movie opened. The colored rectangles on the black board are drawn based on the data in the XML file. If you'd like to see the content of the loded XML file, click the arrow button below.";

createDrawings();

btnShowFile.visible=true;

ldr.removeEventListener(Event.COMPLETE, loadComplete);

ldr.removeEventListener(IOErrorEvent.IO_ERROR, loadError);

}

 

function loadError(e:IOErrorEvent):void {

txtOutput.text = "Error reading the data file. The server may be busy. Try refreshing the page.";

}

/*
It is the function 'createDrawings' below that accesses and proccesses the data from the loaded rectdata.xml file. Recall that the data is stored in the variable xmlContent. In order to understand what the function does, you need to look at the structure of rectdata.xml above. Not to interrupt the flow of the code, we place our comments about the 'createDrawings' function in the next section.
*/

function createDrawings():void {

var i:int;

var numRecs:int = xmlContent.rec.length();

var lineThick:Number;

var lineColor:int;

var fillColor:int;

var recWidth:Number;

var recHeight:Number;

var recStartX:Number;

var recStartY:Number;

for (i=0; i<numRecs; i++) {

recStartX = Number(xmlContent.rec[i].startpoint.@ptx);

recStartY = Number(xmlContent.rec[i].startpoint.@pty);

recWidth = Number(xmlContent.rec[i].dimensions.@w);

recHeight = Number(xmlContent.rec[i].dimensions.@h);

fillColor=int(xmlContent.rec[i].look.fillhex);

lineThick = Number(xmlContent.rec[i].look.strokethick);

lineColor = int(xmlContent.rec[i].look.strokehex);

drawings.graphics.lineStyle(lineThick, lineColor);

drawings.graphics.beginFill(fillColor);

drawings.graphics.drawRect(recStartX,recStartY,recWidth,recHeight);

drawings.graphics.endFill();

}

}

/*
The button btnShowFile when clicked displays the content of our xml file in the text field on the stage. Note the use of the 'toString()' method.
*/

btnShowFile.addEventListener(MouseEvent.CLICK, displayFile);

 

function displayFile(e:MouseEvent):void {

txtOutput.text = xmlContent.toString();

verScrollBar.visible=true;

verScrollBar.update();

}

 

function drawBoard():void {

board.graphics.lineStyle(1,0xFFFFFF);

board.graphics.beginFill(0x000000);

board.graphics.drawRect(0,0,260,285);

board.graphics.endFill();

}

 

Comments About Accessing the XML Data within 'createDrawings' Function

There are many different ways of processing XML data and accessing an XML object's elements. In this How - To, we chose the simplest and the most intuitive variable-type syntax, and this is what you see within 'createDrawings' function. To understand what happens in 'createDrawings', you have to look at rectdata.xml file and observe the tree-like structure of elements and attributes in it.

rectdata.xml contains the root element 'rectangles' -- everything is enclosed between <rectangles> and </rectangles> tags. This 'root' element as such is for all practical purposes ignored by the AS3 parser although its presence is necessary. The next level in the tree-like hierarchy of rectdata.xml consists of the three <rec> elements, each containing the data for one of the three rectangles. Each <rec> element (or 'node') contains three child nodes: <dimensions>, <startpoint>, and <look>. The <look> element contains three child nodes of its own <fillhex>, <strokehex>, and <strokethick>. Between each of these three tags <fillhex>...</fillhex> etc., we arrive at the bottom of the hierarchy, at the 'text nodes'. For example, 0x990099 between fillhex tags:

<fillhex>0x990099</fillhex>

The elements <dimensions> and <startpoint> do not have children nodes but they have the so called attributes. For example <dimensions> element has attributes 'w' and 'h':

<dimensions w="50" h="80" />

Attributes are accessed a bit differently than child nodes.

Recall that 'xmlContent' contains the XML object created from the loaded rectdata.xml file. Let us now examine how the function 'createDrawings' processes the data stored in 'xmlContent'. The rectdata.xml file contains three <rec> elements. Thus, the value of xmlContent.rec.length() is 3. Note the dot syntax to access children nodes.

We have three <rec> elements. We use bracket syntax to access the consecutive <rec> elements: xmlContent.rec[0], xmlContent.rec[1], etc. Within our loop, we have xmlContent.rec[i] for i=0,1,2. Since every <rec> element contains only one child node named <look>, we can write: xmlContent.rec[i].look instead of xmlContent.rec[i].look[0]. Each <look> node has three children nodes <fillhex>, <strokehex>, and <strokethick>, and only one of each. So we use the same dot syntax to access them: xmlContent.rec[i].look.fillhex, etc.

Finally, through the sequence of nested elements we get to the end at which we have a so-called text node. For example, the one between <fillhex> and </fillhex>:

<fillhex>0xCCCC00</fillhex>

Despite the name 'text node', the value 0xCCCC00 is of the datatype 'xml' and not 'string'. It needs to be converted to the datatype that it represents for us, in this case to 'int'. Thus, we use: int(xmlContent.rec[i].look.fillhex). If you wanted the content of a text node to be converted to a String, you would use the important XML.toString() method. For example, xmlContent.rec[0].look.fillhex.toString(); would return the String "0xCCCC00".

How do we access attributes? Let's take for example, the first <rec> element in which we have:

<startpoint ptx="30" pty="20" />

We access the attributes ptx and pty using the '@' syntax. For each i=0,1,2:

xmlContent.rec[i].startpoint.@ptx

So, xmlContent.rec[0].startpoint.@ptx, after conversion to a number, equals 30.

In our example, we tried to name our XML elements so that their names would not represent keywords in AS3 and would not display in blue when accessed. The effort is not necessary. AS3 will not become confused if your tags do correspond to key words, like our, for example, tag 'dimensions'.

Finally, let us comment on the use of attributes versus additional elements. Why use for example:

<startpoint ptx="30" pty="20" />

instead of:

<startpointx>30</startpointx>

<startpointy>20</startpointy>

No particular reason. It is a matter of style. Whichever way feels more natural in a given XML data.

Back to AS3 How To and Tips              Back to Flash and Math Home

We welcome your comments, suggestions, and contributions. Click the Contact Us link below and email one of us.

Adobe®, Flash®, ActionScript®, Flex® are registered trademarks of Adobe Systems Incorporated.