Data from XML within Flash
The above example was just a trivial intro to loading XML into Flash, now let's look at actually using some information we've loaded. First we'll need an XML document with some more useful information. I had a great idea for a project to work through with you all via this tutorial but now I've forgotten it, so I'm going to go back to the Amazon example I gave above. Here is a snippet from the result of a query on the Amazon Web Services 2 XML server, looking for books with the word "flash" in the title. (Note that the first line has been cut short to fit the window of this tutorial.)

<Details url="http://www.amazon.com/exec/obidos/redirect?tag=webservices-20%26creative=...">
         <Asin>059600396X</Asin>
         <ProductName>ActionScript for Flash MX: The Definitive Guide, 2nd Edition</ProductName>
         <Catalog>Book</Catalog>
         <Authors>
                  <Author>Colin Moock</Author>
         </Authors>
         <ReleaseDate>19 December, 2002</ReleaseDate>
         <Manufacturer>O'Reilly & Associates</Manufacturer>
         <ImageUrlSmall>http://images.amazon.com/images/P/059600396X.01.THUMBZZZ.jpg</ImageUrlSmall>
         <ImageUrlMedium>http://images.amazon.com/images/P/059600396X.01.MZZZZZZZ.jpg</ImageUrlMedium>
         <ImageUrlLarge>http://images.amazon.com/images/P/059600396X.01.LZZZZZZZ.jpg</ImageUrlLarge>
         <ListPrice>$54.95</ListPrice>
         <OurPrice>$38.47</OurPrice>
</Details>

You'll notice that this document is a lot more complex than any of our previous examples, but don't let that scare you off. Take a moment to read through it and you will see that it is in fact a very nice representation of all the information relevant to a particular book. I've used indentation to indicate the hierarchy of the nodes. Notice that the Details node is the major node, and it contains all the other nodes, such as Asin, ProductName, etc. as its children. Also note that the Authors node, which is a child of the Details node, has its own child node. This is because there can be more than one author who contributed to a book, so had this book had multiple authors, they would each be listed here in a separate Author node, as a child of the Authors node. Thus each Author node is a 'grandchild' of the Details node.

You may wonder why I'm using terms such as child and grandchild. This is the common method for referring to the structure of XML. Moreover, it is the exact terminology Flash uses when manipulating XML documents, so I'm trying to acclimatize you to it.

Imagine that these nodes were laid out in the format of a family tree.


Figure 1: Tree representation of sample XML document

The above diagram clearly shows that each Author node is a child of the Authors node and a grandchild of the Details node, which is the 'root' (top) node of the tree in this example.

Because XML is hierarchical, in order to access information stored deep within an XML document, such as the name of the first contributing author to a book in our example, we must pass first through the root node, then through the appropriate child, to the grandchild and extract the information. This process is often called 'drilling-down' or 'parsing', and can be quite involved with complicated data structures.

Let's take a look at some code. You may wish to download the source file to this example (example2). I've set up an XML document with the exact Amazon XML from above copied into it and named it book.xml. I've created a new FLA named 'drill_down.fla' and into the first frame I've put this code:

// Create new XML Object and set ignoreWhite true
book_xml = new XML();
book_xml.ignoreWhite = true;
// Setup load handler which just invokes another function
// which will do the parsing of our XML
book_xml.onLoad = function(sucess) {
        if (sucess) {
                processBook(book_xml);
        }
};
// Load up the XML file into Flash
book_xml.load('book.xml');
// This is the function that will be called when
// our XML document is loaded succesfully
function processBook(xmlDoc_xml) {
        // xmlDoc_xml is now a reference to the XML
        // object where our information is stored
        for (a in xmlDoc_xml.firstChild.childNodes) {
                trace(a + ' ' + xmlDoc_xml.firstChild.childNodes[a]);
        }
}

This is nothing new, it's just like our earlier example of how to load up XML except that the onLoad event handler now invokes another function which we can edit to perform operations on the XML object. At present that function just outputs the contents of the XML node to the Debugging window so we can check everything is running well.

All manipulations of the XML object will now be made within the processBook function, which accepts a reference to an XML object. We're passing in this reference instead of hard coding 'book_xml' into the function so that the function can be reused for another XML object if we wish to load in another XML file and call it something different. Looking back at our simple diagram above we see that the Details node has many children.

Say we are creating an application which needs to display information about a book drawn from an XML file. The first thing we'd want to display is probably the Title of the book, which in this case is given by the ProductName node of our XML ('Product' instead of 'Book' because Amazon sell everything from books to clothes now).


Figure 2: The virtual pointer within Flash

When referencing nodes within an XML document, we have a virtual pointer which keeps track of where we are in the tree structure. To begin with the pointer is pointing at the XML document (not the first node), as shown in panel 1 of Figure 2 above.

In Figure 2 above we can see that the Details node is the first node of the XML document, or the 'first child' of the document. We can move our virtual pointer to the Details node using the following code. This is also illustrated in panel 2 of Figure 2.

trace(xmlDoc_xml.firstChild);

The 'first child' of the Details node is the Asin node, so what do you think this code will do? (Here's a hint, it's shown in panel 3 of Figure 2!)

trace(xmlDoc_xml.firstChild.firstChild);

If you expected it to trace the Asin node, then you'd be correct. The important thing to note here is that it traces the tags as well as the node's value, which illustrates that the theoretical pointer which keeps track of where we are in an XML document is pointing to the Asin node, not the text within it (panel 3,Figure 2). To access the value of the node (the text within the tags) we need to add an additional call to firstChild, as follows (see panel 4, Figure 2):

trace(xmlDoc_xml.firstChild.firstChild.firstChild);

While this outputs the value we're after, we are supposed to use the nodeValue property of the XML object to get at it, so the proper way to get the value of the Asin node is using this code.

trace(xmlDoc_xml.firstChild.firstChild.firstChild.nodeValue);

We use nodeValue for an accurate representation of the string value of a node. For example, in strings which include special characters such as ampersands (&) using nodeValue results in the returned string including the ampersand character (rather than the encoded string '&' which is used to represent an ampersand). Thanks to Jeff Schuster for being the only person around to figure that out and explain it to me.

Easy huh? So what if you wanted to access the ProductName node which is the second child of the Details node? This can be done using a similar sort of approach, by reaching the Asin node and then asking for the nextSibling, which moves our theoretical pointer to the next node at the same level in our tree diagram above.
We first use two calls to firstChild to go to the Details node (Figure 3, below, panel 1), then the Asin node (panel 2), then one call to nextSibling which moves us to the ProductName node (panel 3), then one call to firstChild to get inside the ProductName node (panel 4) and finally a call to nodeValue.


Figure 3: Referencing using nextSibling

The code looks like this:

trace(xmlDoc_xml.firstChild.firstChild.nextSibling.firstChild.nodeValue);

Low and behold this traces "ActionScript for Flash MX: The Definitive Guide, 2nd Edition" just as it should.

We'll discuss another method over the page...