The Wayback Machine - https://web.archive.org/web/20080704203050/http://developer.yahoo.com/flash/articles/e4x-beginner-to-advanced.html

Developer Network Home  Help 

YDN Flash Developer Center Articles - E4X: Beginner to Advanced
Flash Developer Center

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.

Navigation

  1. Introduction to E4X
  2. Using Namespaces with E4X
  3. Common Problems and Special Cases

What You Need

Part 1: Introduction to E4X

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 CHANGE event.

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 XML type.

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.

Part 2: Using Namespaces with E4X

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:

http://weather.yahooapis.com/forecastrss?p=94089

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.

Part 3: Common Problems and Special Cases

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!

Consider a situation where you want to retrieve all the paragraphs in an XHTML document. Each paragraph could be nested in DIVs, lists, tables, or anything. If we want to retrieve an XMLList of every paragraph in that document, we need to use E4X's .. operator. A single dot only allows you to access direct children of a node, but this operator allows you to drill-down into the hierarchy of every descendant in an XML object to access grandchildren and more.

You can combine this new operator with the filtering methods I introduced in Part 1 to build some pretty complex queries. The following example retrieves the URLs from all the anchors (links) in unordered lists with the class name "links". Notice that I must use brackets notation [] because the word "class" is an ActionScript keyword.

You will discover, if you try to run the code above, that Flash Player will throw an error message. Why does this happen? Well, looking more closely at the XHTML document, you should see that the second link, the one that points to Adobe's website, doesn't have a class attribute.

You can work around this problem by using the attribute() function to access the "links" class instead. This function does not thrown an error if an attribute doesn't exist. The example below demonstrates the minor change needed to stop the error.

Let's combine the original example, where we can query every single item in the whole document that matches certain conditions, with the last example, where we access an attribute with a reserved name. We'll use the descendants() function, which returns every element that is below an XML node. This function works a lot like the .. operator because is not limited to direct children. We'll combine it with the attributes() function that we used in the last example.

You'll notice that the query returns every single class attribute in the document, including duplicates. For instance, there are two links in the document that I have given the class name "josh" because they happen to point to sites that have content created by me (my personal blog, and of course, you're reading content on the Yahoo! Flash Developer Center right now). What if I want a list containing only unique items? In other words, how can I get a list of class names where "josh" only appears once?

Unfortunately, E4X doesn't provide a native way to retrieve a list with only unique values. That's unfortunate because I've found that it is a common requirement. Based on our previous knowledge of combining E4X with ActionScript (remember the trace() call from Part 1?), I built the following query that should do the job:

The query calls a simple function named addUniqueValue(). Yes, you may call functions that return values in E4X queries too!

Code within parentheses in an E4X query basically runs in a loop for every item in the XMLList. I've used this to my advantage to call a function for each item in the list that checks to see if the item has been included in the filtered list. Once the full query finishes, an XMLList with unique items will be placed into the filteredClasses variable. By the way, did you notice that XMLLists support the += operator to append additional items? It's a nice shortcut to help you write leaner code.

Welcome Experts!

That should cover just about everything you need to know to go crazy with E4X. Keep in mind that E4X can be a bit slow if written poorly, and it's important to optimize your queries for large datasets. If you need to filter your data, like I did to get a list of unique values, remember that you can call ActionScript functions and assign values directly within the parentheses. Finally, don't forget about functions like attribute(), descendants() and child(). Now, go out there and parse XML like you've never parsed it before!