E4X: Beginner to Advanced
by Josh Tynjala, Flash Platform Engineer
This article is based on original work published on Josh Tynjala's blog.
ActionScript 3 in Flash Player 9 includes powerful support for reading and manipulating XML data. ECMAScript for XML, or E4X for short, offers ActionScript developers some useful and exciting new syntax. An introduction to the very basics of E4X, a look at namespaces, and exploration of special cases and potential problem areas should give anyone the skills needed to become an E4X expert.
E4X uses the new top-level XML and XMLList classes. The simplest and most common way to declare a variable of one of these types is to pass String data formatted as XML to the constructor. However, many developers might miss the fact that one can declare XML directly within your classes or ActionScript code--not as a String, but natively. The compiler can understand it perfectly.
Here's an example.
E4X lets you drill down into the data to get the information you need without any excessive looping or strange calls to parent and child nodes. The following example gets a list of all the item names defined in the XML I introduced in the previous code block. Notice that the name attribute is specified with the "@" symbol at the beginning. This symbol helps to differentiate between child elements, like "source" or "price", and attributes, like "name".
To take things a step further, let's filter the same set of data to find items with "Amazon" defined as the
source value. You can place an ActionScript statement within parentheses to filter on specific values. In this case, we check to see if an item's
source element is equal to the string value "Amazon".
You may be surprised to discover that you can place just about any ActionScript statement within the parentheses. In the following example, I've included a
trace() statement to display each item's name in the output console (if you are using Flex Builder or Flash CS3). I find this particularly useful for debugging complex E4X queries.
When using parentheses to filter data, you don't need to filter against a single attribute or element. You can easily filter by multiple fields too. This next example filters items from Amazon with a price under $400.00.
It gets more powerful than that, actually. Say that your application filters items by source, like in the example where we only wanted items from Amazon. However, imagine that the filtering is controlled by the user through a ComboBox or another user interface component. E4X will let you compare attributes or children against a variable too! It should be easy to update the following example to set the source name from a ComboBox's selected item in an event handler for the ComboBox's
You must be certain that the variable name is different than the name of the child. If I had named my variable
source, instead of
sourceName, the statement within the parentheses would never access the item's
source element because it would always use the local variable instead. In exact terms,
(source == source) most definitely will not work!
What happens if the name of the value by which we're filtering should be dynamic as well? For example, if you've ever used "Smart Playlists" in Apple's iTunes, you know that you can choose to filter by Genre (the field), and you may also type in "Rock" (the value) and it will filter your playlist to only display the Rock genre.
In the previous examples, we've accessed attributes directly with the @ symbol and the attribute name, but our attribute will be stored in a variable. Thankfully, we can call functions that are available on the XML object too. Here, we call the attribute() function to get an attribute's value by passing its name. You may also use the child() function here, along with several others defined by the
The examples above should give you a pretty good understanding of E4X basics. Parts two and three will start focusing on real-world examples including the use of namespaces, which are very common in public XML APIs, and we'll look at some special cases you might encounter with XHTML and other complex XML types.
Sometimes, when working with XML from webservices or public APIs, you will encounter certain elements or attributes inside namespaces. For instance, the Yahoo! Weather RSS feed has a "yweather" namespace that adds certain new elements to the feed that aren't part of the regular RSS standard. To use E4X with complex XML like this, you'll need to know a couple of things to make this namespaced data accessible.
For the following examples, I will be using the Yahoo! Weather feed for Sunnyvale, CA. It is available at the following URL:
There are two ways to use namespaces in your E4X statements. You can reference the namespace directly in your query, or you can declare the namespace available for use globally. Regardless of which method you use, you'll need to declare the namespace first. Notice that it is defined by a URL. I've taken this value directly from its declaration in the RSS feed itself.
Now that we have the namespace accessible to ActionScript and E4X, let's access the current temperature using the namespace as part of the inline query.
It's simple, but as you can probably imagine, a more complex query will require too many references to the namespace. Alternatively, if you don't want to litter your queries with references to yweather::, you can tell the compiler to always use this namespace when it is needed.
Now, we can write a simpler E4X query without the need to worry about our namespace:
As you can see, using namespaces with E4X is very easy. Quite a few developers trip up on it the first time they encounter a namespace, but once you get the hang of using them, you'll barely notice that they exist.
Sometimes, when you're working with XML, you may not know for sure which attributes exist on a particular element. Using the Yahoo! Weather RSS feed from Part 2, let's look more closely at the
condition element. We want to get a list of its attributes and trace the name of each attribute along with its value. Don't forget to use the yweather namespace before running this code!