You are on page 1of 15

AS3 E4X Rundown dispatchEvent() Blog

http://dispatchevent.org/roger/as3-e4x-rundown/

dispatchEvent() Blog
Collective thoughts on Flash Platform and iPhone OS programming The ActionScript 3.0 Bible Cometh Apollo FileSystem Tutorial Part 1 File and FileStream

AS3 E4X Rundown


May 21st, 2007 by Roger Braunstein

View this article in other languages: Chinese translation by Wei Gao

Ive been using E4X in ActionScript 3.0 for a while now and the rumors of its simplicity have been greatly exaggerated. A lot of operations are easy and make sense, but others are less obvious. E4X is essentially a whole new language which is part of the AS3 grammar, just as regular expressions have their own completely dierent language but exist within ActionScript 3.0. And being so new, there really isnt a whole lot of documentation out there. This is further complicated by the fact that since E4X seems simple enough at rst glance to explain in a few lines, a lot of documentation stops short. Anyway. Ive been infuriated by E4X more than a few times now, and Id like to start a running post to demystify some of it. Please! use the comments to ask any questions you might have, and Ill keep adding to this post. Hopefully this can turn into a decent resource for E4X lore. The fun begins after the cut. For the following post, lets use this XML block as an example:
var thePeople:XML = <people> <person name="Mims Wright" suffix="III"> <age>27</age> <aka>Mims H Wright</aka> <aka>Teh AWesoeomes!</aka> <bio><![CDATA[This guy <b>rulz<b>!]]></bio> </person> <person name="Roger Braunstein"> <age>26</age> <aka>Rog</aka> <aka>That guy</aka> <bio><![CDATA[Likes food.]]></bio> </person> </people>;

1 de 15

20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog

http://dispatchevent.org/roger/as3-e4x-rundown/

XMLList vs XML
Ok, first thing you notice is that you can just type in XML and it becomes an XML typed variable. You should also know that this XML class is not the same as the XML class in AS2. All new! Second thing you should know is that there are two principally related classes: XML and XMLList. XML is well-formed XML (mostly; see Node Types for exceptions). XMLList is a list of XML nodes. The difference here is that XML must always have one single root node; XMLLists have multiple nodes at the base depth. For instance, the whole example above is XML because it is typed as XML and it has a single root node, <people>. In contrast, an XMLList is composed of zero or more root nodes, like:
<age>27</age> <age>26</age>

This cant be XML because there are two root nodes. You can, however, think of it as a list of XML, since each <age> node is itself a single root node. Its important to note that an XMLList can also have one (like XML) or zero nodes. Anyway, most of the basic operations for E4X are ltering operations. You take the XML and nd some subset of the XML. Often, you want to nd a particular node. Any ltering you do is going to result in a number of possible nodes, so you will notice soon that XML always turns into XMLList when you lter it. Most of the time youll be dealing with XMLLists. The same kinds of lters are available on both classes, except where noted.

The Basics
These are the basics of E4X. Youve probably gured these ones out already cuz you is a pimp!
thePeople.person.age

Use dot syntax to select child nodes by name. The variable is already associated with the root node so theres no need to write <people> into the expression. The expression above has two successive filters. The first one gets you all the <person> nodes immediately below the root node, in other words, an XMLList. The second one gets you all the <age> nodes below all the nodes in the first filter. Result:
<age>27</age> <age>26</age>

Again, this is an XMLList, and notice how it retrieves all the age nodes under all the person nodes.
2 de 15 20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog

http://dispatchevent.org/roger/as3-e4x-rundown/

thePeople.person.@name

Use the @ symbol to select attributes instead of child nodes. This example is two subsequent filters. The first finds all the <person> nodes under the root, and the second finds all the name attributes of those nodes. This time, the result is not a list of nodes but a list of attributes. It gets weird here, but the result is an XMLList of attributes. This sure isnt valid XML, but well talk more about node types later.
thePeople.person.(age >= 21)

Possibly your most powerful tool, a parenthetical can lter nodes based on arbitrary criteria. This expression returns an XMLList with both Mims and I because were both totally legal drinking age AWESOME! Another expression you could create:
thePeople.person.(@name.charAt(0) == "R"); //Roger's <person> node thePeople.person[1]

Use square brackets to get XML nodes out of XMLLists, like an indexed array. This is your way to get from XMLList to XML. Result:
<person name="Roger Braunstein"> <age>26</age> <aka>Rog</aka> <aka>That guy</aka> <bio><![CDATA[Likes food.]]></bio> </person>

Also, since all lters available to you return all possible matches, when searching out a specific node youll use this all the time. For instance, you can create a sequence of lters that should only have one match, but you might nd yourself picking out the rst result of every test. E.g.,
thePeople.person.(@name == "Roger Braunstein").age; //XMLList with one node thePeople.person.(@name == "Roger Braunstein")[0].age[0]; //XML

I think its kind of unfortunate that theres no shortcut to pick the only result of a lter, because complex E4X expressions can frequently become polluted with [0]s. Alternately, you can just place one at the end of a chain of lters. In the second example above, the expression goes from XMLXMLListXMLListXMLXMLListXML.
thePeople..age

Using two dots instead of one ( ..) finds all the applicable nodes that are at any depth rather than at the the next depth. It lets you search for descendents instead of children. For example, you could find all <div> tags in

3 de 15

20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog

http://dispatchevent.org/roger/as3-e4x-rundown/

an XHTML document this way. The result of this query is:


<age>27</age> <age>26</age>

We didnt bother to look for the anywhere in the XML.


thePeople.*.age

<person>

tags; those

<age>

tags can come from

The asterisk operator (*) selects all children of the node. If the example had a non-<person> tag with an <age> child, this line would return it as well as the <age> nodes under the <person> nodes. It doesnt care what the rst generation child is, as long as the second generation child is <age>

Strings and XML


When youre printing out XML elements, if you dont specify a dierent conversion function, toString() is called. This will print out complex content like XML and simple content like its string value. You can use hasSimpleContent() and hasComplexContent() to test these: simple content are text nodes, attribute nodes, or a single XML element with no XML node children (such as <age>26</age>). This means you can print out my age with:
trace(thePeople.person.(@name == "Roger Braunstein").age); //26

Even though this expression returns an XMLList, that list happens to have just one element, an XML node with a text child, and XMLList.toString() prints out its text value, 26. The same applies for:
trace(thePeople.person[0].@name); //Mims Wright

Use toString() as a simple way to get text content out of attributes and simple XML containers like <age>26</age>. If you want to ensure that the content prints out like XML, use
toXMLString().

trace(thePeople.person.(@name == "Roger Braunstein").age.toXMLString()); //<age>26</age>

You can use the text() filter to grab text nodes out of XML. For instance, grabbing an attribute like thePeople.person[0].@name returns a text node. The only child of <age>26</age> is a text node.
trace(thePeople.person[0].age.text()[0]); //27

Again, this filter returns an XMLList of all the text nodes found, and we use array access to grab the first one. We could extract a list of all of the text nodes inside all the age tags with the following:

4 de 15

20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog


trace(thePeople..age.text()); //2726

http://dispatchevent.org/roger/as3-e4x-rundown/

Note that toString() doesnt add any space. text nodes, it prints out as:
27 26

toXMLString()

does, but since theyre both

Function-style Properties
In E4X, using a property name in an expression finds child nodes with the specified name, like thePeople.person. We want to be able to name XML nodes anything we want, so all the filters, calculated properties, and functions of XML nodes are implemented as functions. In other words, thePeople.person.length would look for <length> nodes in the XML; but we can find the number of <person> nodes with:
thePeople.person.length(); //2

All the tests and filters are implemented as functions, even if corresponding properties in other classes are implemented as implicit accessors.

Synonyms, Other Axes


An axis is a direction of movement. In space, we can travel over the axes x, y, and z. In XML, however, we can travel down to child nodes, sibling nodes, and the like. In the E4X vs. XPath comparison, E4X loses out on axes big-time. Its missing several important ones. In the basics, I covered a bunch of directions you can travel already. Those were actually shortcuts for more verbose functions. This list will show which shortcuts exist.
attribute(name), attributes()

These axes find attributes of the corresponding XML. The first filters by the name of the attribute, and the second retrieves a list of all attributes. Their shortcuts are @name and @*. Important! The attribute(name) axis will frequently serve you better than the @name shortcut! The shortcut only works when the attribute exists on all nodes in the list. This is a huge limitation, and a good reason to use the function version.
thePeople.person.@suffix; //OK, list of all suffix attributes thePeople.person.(@suffix == "III"); //ERROR!!! thePeople.person.(attribute("suffix") == "III"); //OK, Mims' node

5 de 15

20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog


child(name), children()

http://dispatchevent.org/roger/as3-e4x-rundown/

These axes nd the children of the given node[s]; by child I mean a rstgeneration descendent. The rst nds a child of a specific name, and is the same as typing that name in literally. The second nds all children, which weve seen before as the asterisk operator. The following holds true:
thePeople.child("*") == thePeople.children() == thePeople.*

There are benefits to using this (and all the filters) as axis functions rather than shortcuts. The major benefit is that you can use a variable name as the parameter to an axis function.
var interestedNode:String = "bio"; thePeople.person[0].child(interestedNode); //Mims' bio

You can also pass an index to child() to retrieve a child at a certain index, just like using the array access notation. In my opinion this is more confusing than helpful.
descendants(name)

This axis returns all descendants (children, grandchildren, etc.) of a node set whose node name matches the name passed. Unlike child() and children(), this axis has one function, but if a name is not passed, it will return all the descendants. In other words, it defaults to *. Its shortcut is the double dot (..).
thePeople..age == thePeople.descendants("age") thePeople..* == thePeople.descendants() == thePeople.descendants("*") parent()

This axis returns the nodes parent or nodesets immediate parents. There is no shortcut for this. For instance:
var age0:XML = thePeople..age[0]; //<age>27</age> trace(age0.parent().@name); //Mims Wright

Do you notice whats missing? Yes, siblings would be really nice. It was so easy in AS2 to use nextSibling and previousSibling. But believe it or not, you have to hack your way around this by going to the parent and finding the next index. This is my workaround for sibling traversal. Let me know if you have a better one.
var node:XML = thePeople.person[0]; //in general, for any node: node.parent().children(); //all siblings

6 de 15

20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog


node.parent().*[node.childIndex() + 1]; //next sibling node.parent().*[node.childIndex() - 1]; //previous sibling

http://dispatchevent.org/roger/as3-e4x-rundown/

The ancestor axis (parent, grandparent, great-grandparent, etc.) is also missing from E4X.

Node Types
In addition, there are axes which select specific kinds of nodes. In actuality, an XML instance can hold a node of any type: element, comment, text, or processing instruction. This means that XML typed variables arent always valid XML documents. A text node by itself is not valid XML. You can use the nodeKind() function to identify the type of a node. It will return element, comment, text, or processing-instruction. Note also that processing instructions and comments are typically ignored unless you change those settings on the XML object. The elements(), comments(), types as children.
text(),

and

processingInstructions()

axes select nodes of these

Creating and Updating Values


When you select nodes with a lter chain, youll end up with an XMLList object or XML object. These objects are always pointers to the original data (unless you use copy() to clone them), and they are writable! So you can change attributes and elements that already exist:
thePeople.person[1].age = 80; //sets my age to 80 thePeople.person.age = 80; //ERROR! you can't set multiple elements with one assignment thePeople.person[1].@suffix = "Sr."; //set my suffix to Sr.

You can create new XML nodes, as weve seen, by literally typing them in. In addition, E4X lets you embed variables in XML literals using curly braces:
var names:Array = ["Alice", "Bob", "Ivan"]; var newPerson:XML = <person name={names[int(Math.random() * names.length)]}></person>;

You can use stored values and expressions as not only attribute names, but node names and whole nodes, as well.
var nodeName:String = "age"; var newAge:XML = <{nodeName}>{Math.round(Math.random() * 100)}</{nodeName}>; var names:Array = ["Alice", "Bob", "Ivan"]; var newPerson:XML = <person name={names[int(Math.random() * names.length)]}> {newAge} </person>;

7 de 15

20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog

http://dispatchevent.org/roger/as3-e4x-rundown/

You can create XMLList literals by using a root tag with no node name. This is kind of cracked out:
var aliases:XMLList = <> <aka>Elmo</aka> <aka>The Fonz</aka> <aka>Peanut Butter</aka> </>;

Adding Values
There are many ways to append values to existing XML. As with the rest of E4X, there are a lot of shortcuts that sometimes make sense and sometimes not Say I want to add an alias to my name. The += operator is overridden for XMLLists, so you can use this as a quick way to append nodes:
thePeople.person[1].aka += <aka>Rog</aka>; thePeople.person[1].* += <eyes>Brown</eyes>; thePeople.person[1].children() += <test>hi</test>; //ERROR!

Im not sure why the last line doesnt work. You can also immediately set non-extant values to create them, like pushing to an array by assigning to the first vacant index.
thePeople.person[0].eyes[0] = "Green"; //adds <eyes>Green</eyes> to Mims' node.

Perhaps a more sensical way to insert new nodes into existing XML is to use the appendChild(), insertChildBefore(), and insertChildAfter() methods. These methods take the Object type because they will attempt to convert their argument to a String and insert it as text if you dont pass XML. But pass XML, and it will work as you might expect:
thePeople.person.(@name == "Mims Wright").appendChild(<aka>Von Kaiser</aka>);

Deleting Values
There is no corresponding removeChild() method. Instead, the delete operator is your only way to remove values. You can use delete with a single node or a whole XMLList, or an attribute.
delete delete delete delete thePeople.person.bio; //delete all <bio> tags thePeople..bio; //Doesn't work but no error. Why?!? thePeople.person.@suffix; //deletes all suffix attributes of <person> tags thePeople.person.(@name == "Roger Braunstein").*; //clears out children of my node

Namespaces

8 de 15

20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog

http://dispatchevent.org/roger/as3-e4x-rundown/

I can write more about namespaces in a future revision, but for now check out the good discussion started in my previous post, Using E4X? Watch Your Namespaces. Theres one odd addition to the language thats specied in the E4X spec, and thats the construct default xml namespace. Whereas opening a namespace allows you to read in XML in that namespace, setting a default XML namespace will also implicitly apply that namespace to new nodes you create.
var xhtml:Namespace = new Namespace("http://www.w3.org/1999/xhtml"); default xml namespace = xhtml; var xml:XML = <html/>; //notice we didn't set a namespace manually trace(xml.toXMLString()); //<html xmlns="http://www.w3.org/1999/xhtml"/>

Loading External Data


You can convert any String to XML by using the top-level XML() function. This looks like a cast operator and acts like one as well: it converts its argument to the XML type, but instead of just changing the type annotation, it performs a conversion. You can use this function to get XML from other functions and variables:
var xmlString:String = '<root><device name="mouse" buttons="2"><connection type="usb"/></device></root>'; var xml:XML = XML(xmlString); trace(xml.device[0].connection.@type); //usb

You can also use it to load data from an external file with the URLLoader class. Check out the documentation for more info on how to use this class.
var loader:URLLoader = new URLLoader(new URLRequest("http://partlyhuman.com/crossdomain.xml")); loader.addEventListener(Event.COMPLETE, onLoadSuccess); loader.addEventListener(IOErrorEvent.IO_ERROR, onLoadFailure); function onLoadSuccess(event:Event):void { trace("Loaded successfully!"); var loader:URLLoader = URLLoader(event.target); var xml:XML = XML(loader.data); trace(xml.toXMLString()); } function onLoadFailure(event:Event):void { trace("Error loading file: " + event.type); }

Conclusion

9 de 15

20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog

http://dispatchevent.org/roger/as3-e4x-rundown/

75% of what youll need to do with E4X is simple, but there are a bunch of gotchas, and I think its not doing AS3 any favors to try to gloss this over. Im really not sure adding E4X was a great idea certainly native XML and XML literals are excellent. But according to ECMA, the reasoning behind creating a whole new language for ltering when we have existing languages such as XPath and the Selectors API is that they are too dicult to learn, and not simple enough. Im certainly happy that theres some native XML support in AS3, but lets be serious about explaining it. Again, please add your comments, especially if you have any problems! Note: If you are going to include XML in your comment, please convert the tags to HTML entities or they will be eaten! Use this tool.
This entry was posted on Monday, May 21st, 2007 at 8:07 pm and is filed under AS3, Programming. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

117 Responses to AS3 E4X Rundown


Older Comments 1. Andy says: July 6, 2009 at 6:59 pm Great Article! I am new to E4X and this helped a lot. I was wondering if you knew of a way to solve this problem. XML Example Essentially i have an organization chart with n levels. Each Node has one parent but can have multiple other sections or people under it. Is there a way to do a lter on the entire set and subset to lter out all the type=persons. All the lters i have seen require you to dictate what level/root you want to lter on but is there anything that will parse the entire XML le and just return back nodes that have a type != person? 2. LEmlich says: July 15, 2009 at 12:41 pm I must have returned to this post 50 times in the last few months. Today, you saved me hours of work. I was trying to use the shortcut to find elements with a certain attribute and was getting an error because not all elements contained that attribute.

10 de 15

20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog

http://dispatchevent.org/roger/as3-e4x-rundown/

This didnt work var zz:XML = t.*.el.(@axis == evil)[0]; But this did var zz:XML = t.*.el.(attribute(axis) == evil)[0]; The rst form works ne as long as every element contains the axis attribute, but I was getting an axis undened error because that attribute was missing (on purpose) from some elements. This post IS my e4x documentation. 3. Xml, xmllist fundamentals in Flex Create possibility says: September 11, 2009 at 1:54 am [...] September 11, 2009 mukeshinpossibility Leave a comment Go to comments Found the article AS3 E4X Rundown and very easy to understand. Categories: XML Tags: XML Comments (0) Trackbacks (0) [...] 4. Alex says: September 15, 2009 at 5:07 pm Great overview, thanks! Id love to see an example of using using e4x with Flex charting capabilities. So if I have an xml le with 100 countries in it, and I want to display a certain variable for 5 specific countries, how would I do it? Any ideas? 5. Mukesh says: September 16, 2009 at 9:24 am Hi,\nI want to add the child in xmllist at the 0th index. I can not found the solution , but instead I get the solution to add it at the 1st index\n \nxml.book[0]+= child\n\nI want to know how can I add child at the index 0\nThanks. 6. David Hay says: September 24, 2009 at 5:04 am This is a great article, I keep coming back to it. Thanks.\n\nI have one question though, I need to change the childIndex of an xml node. Ive got move up and down buttons on a clip and would like to just move their

11 de 15

20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog

http://dispatchevent.org/roger/as3-e4x-rundown/

corresponding node up or down in the list but I cant see how its possible without looping through them all.\n\nThanks,\nDave 7. Guido says: October 2, 2009 at 4:45 am Hi\n\nwe noticed problems when trying to retreive data when using our own namespace. \n\nThis worked :\n \n\n\n \n 440096\n 195467\n 2009-10-02T09:20:46.45\n\n\nbut this did not\n\n\n \n 440096\n 195467\n 2009-10-02T09:20:46.45\n\n\nAnyone ? 8. Aaron says: October 8, 2009 at 2:11 pm Hey guys,\nI am currently beating my head against the wall trying to clean up the text display from my xml nodes, without going into to much detail I am loading an XML le and displaying a particular node in a dynamic text field. The problem is, the text field is also showing the surround tags not just the node content.\n\nmy relevant code is\nwireXML = new XML(event.target.data);\nvar il:XMLList = wireXML.data.contententries.children();\n\nthis.feedText_1_txt.text = il.headline;\n\nthe textbox actually displays:\n\n\nAny help would be appreciated its possible my head will explode.\n\nThanks\n-Aaron 9. one giant media says: December 5, 2009 at 7:22 pm Can you think of a slick 1-liner to convert an XMLList (somxml.node.@attrib filter results) to an Array? I wish this would work: var _titles:Array = XMLList(someXML.allOfSomeNode.@title) as Array; or XMLList class had something like this: var _titles:Array = XMLList(someXML.allOfSomeNode.@title).toArray(); Without it, I made a Util class with function doing this: public static function xmlListToArray($xmlList:XMLList):Array { var a:Array=[], i:int, t:int = $xmlList.length; for (i = 0; i < t; ++i) a.push( $xmlList[i] ); return a; }
12 de 15 20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog

http://dispatchevent.org/roger/as3-e4x-rundown/

10.

onegiantmedia says: December 11, 2009 at 7:33 pm just noticed in my last comment $xmlList.length should be $xmlList.length() XMLList class is simnilar to an array, but its dierent than array notation (which really makes no sense, adobe).

11.

Jon says: January 21, 2010 at 1:58 pm I have an xml value that is blah=ted, joe frank im wondering if i can look through that value for joe and have it return the node, is that possible solely with E4X ltering?

12.

Mike says: January 26, 2010 at 4:44 pm In your example aboveeach person may have multiple nodes if they have multiple alias associate with their nameis there a way to lter through all of those nodes to pull out the ones you want? examplei want to search through the entire xml and pull out the people that have alias names that equal that guy. you cant just say thePeople.person.(aka == That guy); you can surely have an xmlList of all of the aka nodes and using a for loop go through them all.but is there a shortcut to this?

13.

Web Developer says: January 28, 2010 at 2:04 pm \n! I see all of the \n issues in the comments; and I wonder if ths actually demonstrates my question. I can not seem to pull CDATA text out of your sample correctly if it contains \n or \r and have the return, new line actually work if the text is used. If I directly enter the same text with Actionscript3 it does work. I have tried {\n}, \\n, etc, nothing works. Any ideas?

14.

bub says:

13 de 15

20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog

http://dispatchevent.org/roger/as3-e4x-rundown/

February 14, 2010 at 7:10 pm Hi! Thanks for this article, this is very useful and saved me a headache, glad to find people like you that wants to help us! 15. ActionScript 3, XML and MySQL byK says: February 15, 2010 at 10:43 am [...] XML by gotoAndLearn (gotoAndLearn is an overall great AS3 resource) AS3 101:XML by active tuts + AS3 E4X Rundown by dispatchEvent Using XML in Flash CS3/AS3 by Kirupa Loading XML Data Using AS3 by Flash Speaks [...] 16. pinacolada says: March 3, 2010 at 7:15 pm There is nothing in this article explaining how to read the content of a cdata node. Is it impossible ? 17. Using XML (E4X) inside Actionscript 3 says: March 29, 2010 at 3:41 pm [...] intresting article about xml coud be found here: http://dispatchevent.org/roger/as3-e4x-rundown/ Posted in Flash and [...] Older Comments

Leave a Reply
Name (required)

Mail (will not be published) (required)

Website

14 de 15

20/04/10 23:19

AS3 E4X Rundown dispatchEvent() Blog

http://dispatchevent.org/roger/as3-e4x-rundown/

Typethetwowords:

Submit Comment
dispatchEvent() Blog is proudly powered by WordPress Entries (RSS) and Comments (RSS).

15 de 15

20/04/10 23:19

You might also like