Working with XML, E4X and ActionScript 3


On more than one occasion I have asked developers if they had experience with E4X.  I am often surprised to find that some aren’t sure what this amazing ”thing” is and others have been using E4X without even realizing it!

So, what exactly is E4X?  E4X is basically a Document Object Model (DOM) interface for XML.  What does that mean in English?  Well, if you use JavaScript and/or ActionScript you are using an ECMAScript laguage. ECMAScript languages are very similar in the way in which they handle access to their objects, those object’s children, properties and methods.  Basically, if an item contains another item or property, you can access that child item or property along the lines of ParentItem.ChildItem.  E4X provides us with the ability to do this with XML in ActionScript 3.

Requirements

Adobe Flash CS3

Try / Buy

Source Files

Download

E4X’s Addition to ActionScript 3

Prior to ActionScript 3 you had limited means for accessing nodes in the XML that you were using in your Flash applications.  Many developers relied on third-party implementations of XPath to parse their XML when using ActionScript 2.  Many developers also probably recall the long strings of ActionScript used to target specific nodes when not using XPath that looked something like: first.child.childNodes[0].childNodes[1].nodeValue.  Even less efficient were the number of for loops that were used to parse through the XML nodes and arrays that were used to house them.

ActionScript 3 brought us a very strong implementation of E4X.  This helps us do away with the old methods used for parsing XML.  The XML Class has changed in ActionAcript 3, what used to contain the methods and properties you remember from the ActionScript 2 version of the XML Class is now the XMLDocument Class.  When working with the ActionScript 3 version of the XML Class we will be using E4X to crawl through the data.  Attempting to use the same methods from the ActionScript 2 version of the XML Class on its ActionScript 3 counterpart will meet you with undesired results.

Some Examples of ActionScript 2 and ActionScript 3 XML Parsing

I thought it would be helpful to show some examples of ActionScript 2 and ActionScript 3 parsing XML.  Before we start, let’s look quickly at how we load XML in ActionScript 3 vs. ActionScript 2 (The files used in the following examples are available for download).

The XML We Will Be Loading (animals.xml)

<?xml version="1.0"  encoding="UTF-8"?>
       <animals>
              <animal  type="dog" name="Fido" age="2">Fido is a good  dog.</animal>
              <animal  type="dog" name="Ralph" age="1">Ralph is  brown.</animal>
              <animal  type="dog" name="Brian" age="1">Brian is  Ralph's brother.</animal>
              <animal  type="cat" name="Charlie" age="3">Charlie  likes fish.</animal>
              <animal  type="fish" name="Gulper" age="3">Gulper does  not want to be eaten.</animal>
</animals>

The XML above defines several animals of different types, each with different attributes assigned to them.  Next, let’s look at methods for loading this XML into an ActionScript 2 and an ActionScript 3 file:

Loading XML in ActionScript 2

var xml:XML = new XML();
xml.ignoreWhite = true;
xml.load("animals.xml");
xml.onLoad = onXMLLoaded;

function onXMLLoaded():Void{
       trace(xml);
}

Loading XML in ActionScript 3

var xml:XML;
var urlLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE,onXMLLoaded);
urlLoader.load(new  URLRequest("animals.xml"));

function onXMLLoaded(e:Event):void{
       xml =  new XML(e.target.data);
       trace(xml);
}

In the two examples above, we load our animals.xml file and then trace the contents of the XML to ensure that it has been loaded.  Now that we have our XML loaded into memory, let’s look at several scenarios in which we parse the XML.

Parsing The XML

To begin, let’s look at a simple situation.  Let’s retrieve the second animal in the XML data:

ActionScript 2

function getSecondAnimal():Void{
       trace(xml.firstChild.childNodes[1]);
}

ActionScript 3

function  getSecondAnimal():void{
       trace(xml..animal[1]);
}

OK, this example seems simple enough at first glance.  You will notice that the E4X version contains double dots (..).  No, that’s not a mistake.  The use of the .. allows us to basically look at the XML document as a whole and not worry about the schema of the XML.

In the example below, we nested the animal node for “Ralph” within a test node.  The expression xml..animal would still be able to pick up “Ralph’s” node.  This is invaluable when working with complex XML Schemas or when working with XML that may change frequently.

<?xml version="1.0"  encoding="UTF-8"?>
<animals>
<animal type="dog"  name="Fido" age="2">Fido is a good dog.</animal>
<test>
<animal type="dog"  name="Ralph" age="1">Ralph is brown.</animal>
</test>
<animal type="dog"  name="Brian" age="1">Brian is Ralph's brother.</animal>
…

With ActionScript 2 on the other hand, we would require some slightly more sophisticated looping and conditional checking in order to process all of the nodes in the XML document.  Though the use of the .. syntax is quicker for our own coding practices, it is probably more memory efficient and a better coding practice to be as direct as  you can when writing your E4X expressions.

This ability of E4X alone is a major winner in my books!  Let’s take a look at a more details example.

Looking for a Particular Type of Animal

Finding specific nodes in a very large XML file can be daunting.  When it comes to E4X this becomes very simple.  Let’s take a look at the differences between ActionScript 2 and ActionScript 3 for this scenario:

ActionScript 2

//get all animals 1 yr old
function  getOneYearOlds():Void{
       var oneYearOldAnimals:Array = new Array();

       //loop through the XML
       for(var i:Number=0;i<xml.firstChild.childNodes.length;i++){
              if(xml.firstChild.childNodes[i].attributes.age == 1){
                     oneYearOldAnimals.push(xml.firstChild.childNodes[i]);
              }
       }

       trace(oneYearOldAnimals);
}

ActionScript 3

//get all animals 1 yr old
function  getOneYearOlds():void{
       var oneYearOldAnimals:XMLList = xml..animal.(@age == 1);

       //loop through the results
       for(var i:uint=0;i<oneYearOldAnimals.length();i++){
              trace(oneYearOldAnimals[i].@name);
       }
}

Ok, so at first glance it seems like a lot is going on here.  The ActionScript 2 version above, which really could be written any number of ways, looks through the XML, finds nodes with the attribute of age equal to 1 and then pushes them to an Array.  I used this as an example for simplicity’s sake.  Imagine if there were other nodes with an age attribute equal to 1 that we were not interested in.  What if there were animals nested in other nodes?  Both of these cases would require extensive conditionals and loops to be written in order to ensure we gathered only the data we need.  In the case above we are left with an Array containing only text as it has lost all of the XML properties it once possessed.

The ActionScript 3 version of this code introduces some new syntax.  You will see that we loop through all of the animal nodes in the xml.  We create a XMLList variable that holds all of the animal nodes where the age attribute is equal to 1.   Notice in our for loop that we loop while i is less than oneYearAnimals.length().  length()is a method and not a property, forgetting this can drive you nuts while you wonder why your length is not being returned properly.  We then loop through the XMLList and trace out the name attribute of each of the XMLList items.  We are able to do this because they have maintained the XML data originally assigned to them.

Additional Functionality

When you think of your XML like you think about the DOM of Flash it becomes much easier to access the data you are looking for.  In addition to simply returning nodes you can also crawl the XML much like you would nested MovieClips in Flash.  For example, you can access the parent node of a returned node using parent() (once again, notice that this is a method call and not a property):

function getParent():void{
       trace(xml..animal.(@age == 1).parent());
}

In the example above, we find the animals with an age equal to 1 and then request the parent of those nodes.  Tracing out the above result would return the complete <animals> node and its children.

Another handy method is decendants()which will allow you to access every node below a given node in the flow of the XML.  This function another valuable method of the E4X class as it will return more that just the direct children of a given node.

Writing to Your XML Using E4X

Another great feature of E4X is the ability to actually write to the XML quickly and easily.  Keep in mind that when assigning values you will want to directly address a single node and not and XMLList.  In the following example we will set “Ralph’s” animal type to “cat”.

//make Ralph a cat
function makeACat():void{
       var ralph:XML = xml..animal.(@type == "dog"  && @name=="Ralph")[0];
       ralph.@type = "cat";
       trace(ralph.@type);
}

As you can see, we can simply assign values to our XML and then code against them immediately!

Conclusion

This tutorial really only scratches the surface of what is possible using E4X.  As you leverage this new functionality you will see what an invaluable piece of your ActionScript arsenal it will become.


Did you enjoy this article?
Share the love
Get free updates and win TTL prizes

Other Posts You Might Like

17 Responses to “Working with XML, E4X and ActionScript 3”

  1. Niklas says:

    Wow!
    That was an eyeopener for me. I’ve seen all this other tutorials regarding xml in AS3 but they never used the E4X…
    Very nice…

  2. Merijn says:

    I guess I fall in that group that has been using it without realising. This new way of dealing with xml has been one of my favourite AS3 improvements. Great tutorial to, I picked up a few new things along the way.

  3. Carlos Pinho says:

    Keep your eyes on the tuts. More will come. Ah, and if you would like to see a specific tutorial, drop us an e-mail.

  4. Tahir says:

    This is good if you add some thing that how we can get the date and show in the list for example the name of the animals, pics etc if avialable .
    Thanks

  5. How would I use this to populate a list box, then have that info once selected populate a tileList component.

    if the tile List component requires data, and a source, and the list box would be its dataprovider, then how would I pass the description part of the xml?

    I need help.

    I will give my code if need be.

  6. I have the xml formatted the way i need it. The list box displays the galleries just like it is supposed to.

    now the issue is when you click on a gallery, it just steps down the list of images, it does not distinguish the images with that gallery as the xml is formated to do so.

    how would I make the list box, when clicked, only give the info from the gallery list that is associated with tha tgallery?

    any help is greatly appreciated.

    thanks

  7. I have xml format as follows…

    http://www.cbchangar.com/Scripts/test3.xml

    this is the file I am working with right now.

    The list box reads the ‘gid’ tag and takes it for its label.

    I want the tile list to only show the images that are related to the gallery they are associated with. Right now, the tile list only shows one image… not all… why is that?

    thanks so much for the time.

  8. Shane says:

    Good overview – very helpful. Thanks.

  9. Sameer says:

    nice tutorial, getting so many information from this website, keep it man.

  10. Saroj says:

    Thanx for the tutorial . this is my first ever tutorial with XML

  11. Claudio says:

    Hi… i’ve a question:

    Suppose i have this e4x query to parse an xml:

    model.xml..category.(@val==model.category).length( );

    I would like to make dynamic the condition. Something like this:

    model.xml..category.((model.category!=”all”)?@val= =model.category:@val!=model.category).length();

    So, i would like to make two type of search (== or != model.category) in a single query.

    Is this possible in any way?

  12. Just want to say your article is striking. The clarity in your post is simply striking and i can take for granted you are an expert on this subject. Well with your permission allow me to grab your rss feed to keep up to date with forthcoming post. Thanks a million and please keep up the ac complished work. Excuse my poor English. English is not my mother tongue.

  13. Ramesh says:

    I guess I fall in that group that has been using it without realising. This new way of dealing with xml has been one of my favourite AS3 improvements. Great tutorial to, I picked up a few new things along the way.
    This is good if you add some thing that how we can get the date and show in the list for example the name of the animals, pics etc if avialable .
    Thanks

  14. Komal says:

    Thanks for this info. But the code
    trace(xml..animal.(@age == 1).parent());
    in your article doesn’t work. I have been struggling to get the parent node of a node, for which I know the attribute value. But this just doesn’t work… Are you confirmed?

  15. Nimeso says:

    Komal….

    I’ve got same problem. should work but dosn’t does anyone have any ideas? parent() is not working at all when i filter by @ eg:trace(xml..animal.(@age == 1).parent());

  16. Eddie says:

    Great explanation!! It helped me a lot. I only have to do 1 thing now. Can it save the XML file automatically? I Mean I have like this save button, and when it is clicked I want it to make the changes to the XML that already exist.

    Now I use the fileReference Class.

    var fr : FileReference = new FileReference();
    fr.save(ba, “myXML.xml”);

    this works like a charm but…it gives a ‘save as dialog screen’. I don’t want that. I just want that people click the button and that the original XML file is automatically edited. Is this possible?

Leave a Reply

TTL VIP
Become a TTL VIP Member & Get Notified of The Best Changes in Technology, Plus Win Prizes in Our VIP Only Contests...

Tech News Tech Tutorials Smartphone News Tablet News Gaming News Free Software Infographics Contact