Internet / Software Applications

Macromedia Flash MX 2004 ActionScript Programming Tutorial

Using the XML Class to Load and Manipulate XML

XML stands for “extensible markup language”. It’s used to describe data in a way that can be shared across applications, by defining categories for the data and describing the hierarchy of those categories. XML looks very similar to HTML, in that each “category” is defined using opening and closing tags:

<library>

<book>

<title>My Guide to Flash</title>

<author>Jane Doe</author>

</book>

<book>

<title>My Guide to Flash Volume 2</title>

<author>John Smith</author>

</book>

</library>

As you can see, XML uses a tree-like structure to describe a hierarchy of data. Each “branch” on the tree—like <book> and <title>—is a “node”. In our example, “title” is a child node of the parent “book” and “book” is a child node of the parent “library”.

Each opening and closing tag taken together is called an element. The first, or top, element is the root element, which contains all the other elements. The root element is mandatory for an XML document.

Each element can have attributes you define, such as:

<book id=”programming”>

The fewer the nodes in an XML document, the more efficiently Flash can process it. To optimize an XML document for Flash, use attributes whenever possible to describe the value of a node, rather than additional nodes.

A lengthy description of XML is beyond the scope of this tutorial, but it’s enough for you at this point to know that XML is way of describing data, and the description is stored in what is, for all intents and purposes, a text file with the extension .xml. An XML file can be used to relay data among different applications.

Flash is one of those applications. Using the XML class, Flash can load an XML document and interpret its contents, giving you access to the data, which you can then manipulate and present in any way you like. You can send the data somewhere else, either in XML format or not. Flash can also load data not contained in an XML document and then format it as if it were.

Loading an XML Document

As with all of Flash’s other objects, you have to create a new XML object before you can access the XML object’s methods and properties:

var myXML:XML = new XML();

Once you’ve created an XML object, you use the built-in load method to load a file or URL into the movie. This can be a local XML file (on your computer) or an external URL:

myXML.load(“library.xml”);

The URL being loaded doesn’t have to be an XML document—it can, for example, be a server-side script that retrieves data from a database. As long as the script formats the output as XML, Flash can interpret it (although note that the script (or XML file) must be located within your movie’s domain, unless you’re using an executable (Projector) Flash file).

You use the onLoad method to execute actions once a document is loaded into the movie. These actions often let the user (and the movie) know whether or not the document was loaded successfully:

myXML.onLoad = function(success) {

if(success) {

status_txt.text = “Document loaded.”;

} else {

status_txt.text = “There was an error.”;

}

};

The onLoad argument, success, is passed a value of true or false. If the document successfully loaded, it’s passed a value of true, which is inserted into the if statement: if(true)

The onLoad method can also call a function that contains the actions to be performed to manipulate the data.

To get a feel for using these methods, create a new Flash document with a dynamic text field in the first frame. Name the text field “status_txt”. Then add an Actions layer and insert all the code above. Below, you can see what the movie should look like:

Then open Notepad and paste the following text into it:

<?xml version=”1.0″?>

<library>

<book>

<title>My Guide to Flash</title>

<author>Jane Doe</author>

</book>

<book>

<title>My Guide to Flash Volume 2</title>

<author>John Smith</author>

</book>

</library>

Note:

XML tags are case-sensitive. It’s standard practice to use all lowercase, and in your code, you should references elements in lowercase. If you’re ever in doubt about the case of a tag, you can add the toLowerCase() method to a node reference in your code to convert the text to lowercase (node.toLowerCase()).

Save the text file as “library.xml”, placing it in the same directory as your Flash movie.

Now save and test the movie. You should see the following:

Displaying XML Data

In order to manipulate the data in an XML document, you have to access the node containing the value you need. You access nodes using various properties of the XML object:

  • firstChild is the first child node of the current node
  • lastChild is the last child node of the current node
  • childNodes is all the child nodes of the current node
  • parentNode is the parent node of the current node
  • nextSibling is the next sibling node in the list (the next node on the same level as the current node)

We’ll use only two of these methods—firstChild and childNodes—to build a simple “database” front-end that lets the user view information for the books in our XML file:

1.Create a new Flash document with two layers—one for your text and fields and another for actions.

2.In the first frame of your display layer, add a static text title (like “My Library”), two dynamic text fields and two static text labels. One field will display a book’s title—name this “title_txt”. The other field will display a book’s author—name this “author_txt”. Add text to the labels—”Title” and “Author” will do, as shown below:

3.Add 2 button components and name them “Prev_btn” and “Next_btn”. Change their labels to “Previous” and “Next”.

4.Finally, add a third dynamic text field at the bottom and name it “status_txt”. This field will display the load status of the XML document. Since loading of such a small XML file will happen almost instantly, this field isn’t really necessary—or at least, not on this screen—but it’s always a good idea to give the user feedback on what’s happening.

5.Now, select the first frame of the Actions layer and create the new XML object. Load the “library.xml” file you created for the last example:

//create XML object

var Library:XML = new XML();

//load the XML document

Library.load(“library.xml”);

Library.ignoreWhite = true;

You should recognize the first two lines—we’ve created an XML object and loaded the XML document into it. The third line tells Flash to ignore white space. This is important, because ordinarily any white space in a node will be interpreted as another node. However, the ignoreWhite method is only usable for Flash Players 5 and later, so if you’re developing for earlier versions of the Flash Player, you’ll have to add custom ActionScript to handle the white space.

6.Next, we’ll define our onLoad function. Add the following code:

Library.onLoad = function(success) {

if(success) {

status_txt.text = “Document loaded.”;

BookList = new Array();

BookList = this.firstChild.childNodes;

currentBook = 1;

getBookInfo(currentBook-1); //first index position in array is 0

} else {

status_txt.text = “There was an error loading the XML document.”;

}

}

Again, we’re using the onLoad method to test whether or not the document was successfully loaded. For either case (true or false), the status_txt text field is updated with the appropriate text to let the user know.

We’ve also added some lines to the first (true) condition. If the document is successfully loaded, we create a new array called “BookList” and fill it with the child nodes of the first child node of our XML object.

The first child node of our XML object is the first element in the XML document after the XML declaration (<?xml version=”1.0″?>). If you’ve included any other elements, like a document definition, you need to move down in the list to the first element you want to use using the nextSibling property:

this.firstChild.nextSibling.childNodes

Before we move on, it’s important to understand exactly what each item in the array will look like. If you add a trace action to view the output of BookList[0], the first item in the array, you’ll see this in the Output window:

<book><title>My Guide to Flash</title><author>Jane Doe</author></book>

Tip:

If you’ve gotten this far without reading the Debugging section, a trace action simply places the output of whatever you’ve specified in the Output panel when you test the movie. The syntax is as follows:

trace(BookList[0]);

Place the line beneath the line where you add the nodes to the BookList array. Test the movie, and Flash will open an Output window with the value of BookList[0].

As you can see in the output, a single item in the array contains the top-level node you’ve specified for the array as well as all its child nodes. We’ve specified <book> as the top-level node for our array: Library.firstChild.childNodes means “book” is a child of “library”, which is the first child of the Library XML object. So an item in the array includes everything—including all child nodes—that appears between the opening and closing tags of the specified element, or node.

Since we have only two books in our XML document, our BookList array will have only two items. Each will be a “book” containing that book’s information (title, author, etc.).

Next, we declare a variable, currentBook, which we’ll use to keep track of which book the user is viewing. Finally, we call a function named “getBookInfo”, which passes the value of currentBook minus 1 to the function. We have to pass a value of 0 in order to access the first book’s information, since the first index position in the array is 0.

The getBookInfo function will display the first book’s information in our dynamic text fields when the movie first loads. We’re going to define that function next.

7.Add the getBookInfo function, using the following code:

function getBookInfo(num) { //value of num is passed by function call

BookInfoArray = new Array();

BookInfoArray = BookList[num].childNodes;

for (i=0; i<=BookInfoArray.length; i++) {

BookElement = BookInfoArray[i].nodeName; //new variable

if (BookElement == “title”) {

title_txt.text = BookInfoArray[i].firstChild.nodeValue;

} else if (BookElement == “author”) {

author_txt.text = BookInfoArray[i].firstChild.nodeValue;

}

}

}

In the function definition, num is the value being passed to the function from the function call. When the XML document first loads, the onLoad function passes the value currentBook-1, or 0. Later, the value of num will depend on where in the book list the user is when he or she clicks the Previous or Next button, as you’ll see in the next step.

The first lines of the function create another new array, called BookInfoArray, which is then populated by the child nodes of the item in the specified BookList array position. When the movie first loads, the value of num is 0, so the BookInfoArray array is populated with the child nodes of BookList[0], or the first book. The top-level nodes in this new array will be title, author, etc. With this array, we can access the specific information we want—the title and author of the first book.

We do this using a for loop that cycles through each item in the new BookInfoArray array. With each loop, we search for a node named “title” or “author”. Specifically, we declare a new variable, BookElement, which stores the name of the current node for each loop, and then we test whether or not the value of the variable is the node we’re looking for. It isn’t necessary to use a variable—you could place the node reference directly into the if statement—but this makes coding a little easier.

The loop, then, will move through these items in the array:

BookInfoArray[0] = “title”

BookInfoArray[1] = “author”

If we’d had other elements, such as “bookdescription”, “copyright”, “pubdate”, etc., the loop would have cycled through these, as well:

BookInfoArray[2] = “bookdescription”

But the loop would have ignored them, since we aren’t looking for them in the if statement.

With an XML file that only contains a few nodes, you don’t necessarily need to loop through them to find the ones you’re looking for—you’ll probably be able to figure out their index positions. But if you plan to use larger XML files, or to manage the data in any way, you’ll want to understand how to find what you’re looking for in the list. We’re searching first for the node named “title” using the nodeName property of the XML object. If we find it, we assign its value to the title_txt text field using the nodeValue property. Then we search for the node named “author” and assign its value to the author_txt text field.

This function is the meat of our movie—it does almost everything we need. All that’s left is to handle the movement from one book to the next when the user clicks the buttons.

8.We’re going to add 2 more functions, one for moving forward in the list of books, and one for moving backward. These are pretty simple:

function nextBook() {

if (currentBook<BookList.length) {

currentBook += 1;

getBookInfo(currentBook-1);

}

}

function prevBook() {

if (currentBook>1) {

currentBook -= 1;

getBookInfo(currentBook-1);

}

}

In each function, we first test to make sure the user isn’t trying to move beyond the beginning or the end of the array. As long as there is a “next” or “previous” item in the array, then, the actions are executed. Specifically, the currentBook counter is incremented (for nextBook) or decremented (for prevBook), and then the getBookInfo function is called, passing the value of currentBook-1 in order to populate the BookInfoArray with that book’s (currentBook’s) information.

9.The last step is to add our event listeners for our buttons:

Next_btn.addEventListener(“click”, this.nextBook);

Prev_btn.addEventListener(“click”, this.prevBook);

These lines call the nextBook and prevBook functions, depending on which button the user has clicked.

10.Save and test the movie. Use the buttons to move through the list of books:

As you can see, once you understand the hierarchy of an XML document, it’s relatively easy to get at the information in them. Assigning nodes to arrays simplifies locating specific elements in the list.