Using ActionScript to load XML data into Flash
In the previous pages we have defined the mystery words to be used in the game within the ActionScript code, using the following line:
words = ["dog", "elephant", "cat", "giraffe", "lion", "wolf", "ostrich", "penguin", "whale", "raccoon", "tiger", "snake", "lizard"];
This is neat enough, but it means that if we want to modify the list of words we have to open up the FLA file in Flash and modify it there - this might be difficult for some people and it will be impossible if they have only the SWF and not the FLA file. So it would be much better if the word list could be stored in a separate file that could be easily modified using NotePad or Word, for example. An XML file format is suitable for the external file, so that's what we'll use.
| Modify the code by deleting the line shown above that loads words into the words array. | |
| Download this file (words.xml) and place it in the folder where you saved your Flash document. If you want, take a look at it now, but really there is no need — I will discuss and explain it in extensive detail later. | |
| Copy the following code underneath the existing code. |
-------------------------------------------------------------------------------------------------------------------------
// Section 7
var wordsLoader:XML = new XML();
wordsLoader.ignoreWhite = true;
wordsLoader.onLoad = function(success) {
if (success) {
parseWords();
} else {
guessWord_txt.text = "Sorry dude, the
data just didn’t load.";
}
};
wordsLoader.load("words.xml");
// Section 8
function parseWords():Void {
if (wordsLoader.firstChild.nodeName == "gamedata") {
var rootNode:XMLNode =
wordsLoader.firstChild;
for (i=0; i<rootNode.childNodes.length;
i++) {
if (rootNode.childNodes[i].nodeName
== "word") {
var currentWord:String =
rootNode.childNodes[i].firstChild.nodeValue.toString();
words.push(currentWord);
}
}
}
}
---------------------------------------------------------------------------------------------------------
An explanation of the Actionscript code
// Section 7
var wordsLoader:XML = new XML();
wordsLoader.ignoreWhite = true;
wordsLoader.onLoad = function(success) {
if (success) {
parseWords();
} else {
guessWord_txt.text = "Sorry dude, the
data just didn’t load.";
}
};
wordsLoader.load("words.xml");
First, a new XML object is created (wordsLoader). After that, the XML object’s onLoad event handler function is invoked, to check if the loading succeeded or failed. Like before, this function has inside it an if/else conditional statement. If success turns out as true, the parseWords function is invoked (more on that function later). If not, a “I am sorry” message will be displayed for the user. And after that, the actual XML file gets loaded via the XML object’s load function.
Before I explain you the workings of the XML file, there is one line of code that needs to be explained: the second one, with the ignoreWhite property. The ignoreWhite property of an XML object can be set to either true or false. By defining it as true, you tell Flash to ignore all the white space found in the XML file. Why is this necessary? Because white space in an XML file counts as data! Fine. Now that the above piece of code is clear, let me tell you more about XML.
A brief explanation of XML data format and its rules
If you open the file words.xml (which you have downloaded at the start of this tutorial), you will see the following (perhaps without the useful indenting):
<?xml version=”1.0″?>
<gamedata>
<word>dog</word>
<word>elephant</word>
<word>cat</word>
<word>lion</word>
<word>giraffe</word>
<word>wolf</word>
<word>ostrich</word>
<word>penguin</word>
<word>whale</word>
<word>raccoon</word>
<word>tiger</word>
<word>camel</word>
<word>snake</word>
<word>lizard</word>
</gamedata>
Before proceeding, you should know a bit about XML. As you know, most web pages are in the HTM or HTML format: HyperText Markup Language. HTML has a big weakness - its tags can only be used to modify the appearance of the page, not to indicate meaning. So XML was invented to go beyond HTML and allow anyone to include tags that can mean whatever we want. XML stands for EXtensible Markup Language. It is a markup language that describes data. The great thing about the XML data format is that it is platform and operating system independent. This means that an XML file looks exactly the same, whether it is made or read on Linux, Mac, Windows or any other OS or platform. An XML file is basically a text file, with the extension .xml.
When making an XML file, you can use any basic text editor, like Notepad on Windows or SimpleText on a Mac. The important thing to keep in mind is that you should save this file with an .xml extension. Or, you can save it as a .txt file and later change the extension to .xml in your File Explorer.
An XML file can not do anything by itself — it is parsed (read, combed through, looked at) by various programs, browsers, server-side scripts (PHP, Java…) etc if they are enabled to do so. So, you can think of it as a very simple database — stored information.
Unlike an HTML file, where tags are predefined (<p>, <body>, <h1> etc), you are the one who defines the tags in an XML file. This means that you can call your tags any way you like, for example: <flash>, <mysuperbtag>, <anything> etc. But, there are some rules that must be followed. These are really simple, but very, very strict. You must abide by them. Here they are:
| Each XML file must begin with the XML declaration: |
<?xml version=”1.0″?>
This line tells the parser that it’s, well, an XML file. This is not a tag, but just a declaration. So it appears only once, at the beginning of the XML file. Inside it, the version of XML is stated. Also, the character encoding of the file can be included, like this, for example:
<?xml version=”1.0″ encoding=”UTF-8″?>
Since the XML file used in this tutorial is written in English, that additional parameter is not necessary.
| While being composed of different elements, all XML files can contain only one root element. In this example, the root element is <gamedata>. Between the opening and closing tags of the root element, every other element is included. Nothing can be placed outside it: |
<gamedata>
<word>dog</word>
<word>snake</word>
<word>lizard</word>
</gamedata>
Note: I have named each tag within the root element as “word” on purpose (you will see why later). For example, an XML file like this one would be perfectly valid too:
<computer>
<operatingsystem>windows</operatingsystem>
<processor>intel</processor>
<price>expensive</price>
</computer>
| Each element must have a closing tag (except the declaration). So, the following example would result in an error and the XML file couldn’t be parsed: |
<gamedata>
<word>dog</word>
<word>snake
<word>lizard</word>
</gamedata>
| The XML tags are case-sensitive. The opening and closing tags of a node must be exactly the same. Following this rule, this would be ok: |
<word>dog</word>
…while this would cause an error:
<Word>dog</word>
| All the elements of an XML file must be nested correctly. This is an example of proper nesting: |
<diary>
<day>monday</day>
<entry>Another week, another
monday</entry>
</diary>
…while this one is wrong:
<diary>
<day>monday<entry>
</day>Another week, another
monday</entry>
</diary>
Here’s another example. This would be fine:
<flowers><best>rose</best></flowers>
…and this would result in an error:
<flowers><best>rose</flowers></best>
| Any attribute values must be included within quotation marks. A good example of this would be: |
<logentry day=”monday”>Another day at work</logentry>
…while this is incorrect:
<logentry day=monday>Another day at work</logentry>
Also, remember that you can insert as many attributes as you need.
These were the rules for writing proper XML. As you saw, they are really simple. You just have to respect them.
One more thing: as I said before, the white space in an XML file counts as data. That’s why you had to set the ignoreWhite property to true in your ActionScript code previously. This can be circumvented with another method, namely, to leave no spaces between your elements, like this:
<gamedata><word>dog</word><word>snake</word><word>lizard</word></gamedata>
But this is really hard to read and edit. It is much better to put each element of your XML file on its separate line and use the ignoreWhite property.
Cool! Now that you know the XML rules, I will explain you how Flash parses the XML data.
How Flash parses (processes) the XML data
// Section 8
function parseWords():Void {
if
(wordsLoader.firstChild.nodeName == "gamedata") {
var rootNode:XMLNode =
wordsLoader.firstChild;
for (i=0;
i<rootNode.childNodes.length; i++) {
if
(rootNode.childNodes[i].nodeName == "word") {
var currentWord:String =
rootNode.childNodes[i].firstChild.nodeValue.toString();
words.push(currentWord);
}
}
}
}
As I mentioned before, the parseWords function will be called upon once the XML data has been successfully loaded. The first line inside this function is a conditional if statement:
if (wordsLoader.firstChild.nodeName == "gamedata") {
…which checks to see if the first child of the wordsLoader XML object is named (nodeName) “gamedata”. The first child of the wordsLoader XML object is indeed named “gamedata”. I have shown you that an XML file can contain only one root node. The root node is the first child (the first element in the XML file’s hierarchy) of the XML object. In this case, the root node is <gamedata>.
So, there is no need for an if/else conditional statement — an if condition will do, because Flash will read it and see that it evaluates as true. So, it will perform all the code within the conditional statement’s curly brackets:
var rootNode:XMLNode =
wordsLoader.firstChild;
for (i=0; i<rootNode.childNodes.length; i++) {
if
(rootNode.childNodes[i].nodeName == "word") {
var currentWord:String =
rootNode.childNodes[i].firstChild.nodeValue.toString();
words.push(currentWord);
}
}
The first line creates the variable rootNode, which is of the XMLNode type. This variable is created just so that you don’t have to write wordsLoader.firstChild each time (remember, firstChild is the gamedata root node in this lesson’s example). It is merely a shorthand name.
And then the for loop begins, which is used to read all the words that will be used in the game and store them in an array:
for (i=0;
i<rootNode.childNodes.length; i++) {
if
(rootNode.childNodes[i].nodeName == "word") {
var currentWord:String =
rootNode.childNodes[i].firstChild.nodeValue.toString();
words.push(currentWord);
}
}
This loop starts with the variable i set to 0 (zero). The loop will make iterations (i.e. it will repeat itself) as long as its condition evaluates as true. And it will increase the value of i with each loop (i++ means the same as i=i+1). The condition is that i must be less than the number of child nodes of the root node. The number of the child nodes of the root node is retrieved by calling upon childNodes’ length property:
i < rootNode.childNodes.length
In this particular example, this means that i must be less than 14. Why? Because there are 14 child nodes inside the gamedata node:
<?xml version="1.0"?>
<gamedata>
<word>dog</word>
<word>elephant</word>
<word>cat</word>
<word>lion</word>
<word>giraffe</word>
<word>wolf</word>
<word>ostrich</word>
<word>penguin</word>
<word>whale</word>
<word>raccoon</word>
<word>tiger</word>
<word>camel</word>
<word>snake</word>
<word>lizard</word>
</gamedata>
As you can see, each child node of the root node has the name word. This is used by the if conditional statement contained within the loop:
if
(rootNode.childNodes[i].nodeName == "word") {
var currentWord:String =
rootNode.childNodes[i].firstChild.nodeValue.toString();
words.push(currentWord);
}
If the name of the current child node equals “word”, the actions inside the if condition will be performed. Of course, Flash replaces the construct [i] with the current loop iteration number (0, 1, 2, 3 etc), so that it can check each child node: the first one, second… until the last one (which is the fourteenth in this case). Since each child node inside the root one really is named “word”, the following two lines will be executed:
var currentWord:String =
rootNode.childNodes[i].firstChild.nodeValue.toString();
words.push(currentWord);
A new variable called currentWord is created and it is of the String type (meaning it holds a text value). Inside it, the name of the current child node node will be stored:
rootNode.childNodes[i].firstChild.nodeValue.toString();
As you can see in the ActionScript line above, the toString() method is used to convert the value of the child element of each root node’s child node to a piece of text. Because this is XML data (nodeValue), and not text data, it has to be converted to a String so that you can use it later in the game. If this XML order puzzles you, here’s a nice graph explaining the hierarchy inside the XML object:

Once this value is retrieved and converted to text, it is stored inside the words array (which you created in the first lines of your code):
words.push(currentWord);
The push method inserts an element to the end of an array. Since the array is completely empty at the beginning, the first element will be placed on the first place, the second one after that, etc. So, with each iteration of the loop, a word pulled out from the words.xml file will be placed inside the words array. Nice! And easy, as you can see. All you have to learn to be able to make Flash read data from an XML file is write some conditional statements and a loop and that’s it.
Ok, after Flash has executed this chunk of code, you will have all the words from your XML file at your disposal, neatly stuffed into an array. Let me show you now how you can pull a word at random from this array so that the player has a different word to guess each time she plays the game.
Conclusion
The first fact that I want to tell you is that this hangman game (the final SWF file) has a size of only 3 KB! That’s pretty cool! Both the XML and TXT files are so small in size that the whole game loads almost instantly.
You saw how ActionScript helps to streamline tasks that would require too much time to create manually, like the creation of all the alphabet letters’ buttons. Also, like I said before, this Flash game is completely dynamic because once the SWF is finalized, all you have to do to modify the game is change the data in the XML and TXT files.
As for the animation of the hanging, you can make it more complex, even add sound — this is just a question of much time and effort you are willing to put into it.
Pay attention to one important detail: this game supports only one-word guesses. You cannot insert two words inside any of the XML elements (for example: <word>two words</word>), because the code in this lesson isn’t designed to handle non-breaking spaces. However, you have learned a lot and I am sure that you will figure this out by yourself, if you wish to insert this capability into your hangman game.
Extension
An extension to this project is available for faster, more motivated students. It shows how to load data from a text file into Flash using the LoadVars object. Please click HERE to jump to the extension.
