Vous êtes sur la page 1sur 17

AS3 E4X Rundown | dispatchEvent

Pgina 1 de 17

dispatchEvent
Welcome to dispatchEvent, a blog brought to you by Mims Wright of losdesigns and Roger Braunstein of partlyhuman. The ActionScript 3.0 Bible Cometh Apollo FileSystem Tutorial Part 1 - File and FileStream

AS3 E4X Rundown


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

I've 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 different language but exist within ActionScript 3.0. And being so new, there really isn't a whole lot of documentation out there. This is further complicated by the fact that since E4X seems simple enough at first glance to explain in a few lines, a lot of documentation stops short. Anyway. I've been infuriated by E4X more than a few times now, and I'd like to start a running post to demystify some of it. Please! use the comments to ask any questions you might have, and I'll 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, let's 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>;

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 can't 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. It's important to note that an XMLList can also have one (like XML) or zero nodes. Anyway, most of the basic operations for E4X are filtering operations. You take the XML and find some subset of the XML. Often, you want to find a particular node. Any filtering 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 filter it. Most of the time you'll be dealing with XMLLists. The same kinds of filters are available on both classes, except where noted.

The Basics
These are the basics of E4X. You've probably figured these ones out already cuz you is a pimp!
thePeople.person.age

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 2 de 17

Use dot syntax to select child nodes by name. The variable is already associated with the root node so there's 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.
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 isn't valid XML, but we'll talk more about node types later.
thePeople.person.(age >= 21)

Possibly your most powerful tool, a parenthetical can filter nodes based on arbitrary criteria. This expression returns an XMLList with both Mims and I because we're 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 filters available to you return all possible matches, when searching out a specific node you'll use this all the time. For instance, you can create a sequence of filters that should only have one match, but you might find yourself picking out the first 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 it's kind of unfortunate that there's no shortcut to pick the only result of a filter, because complex E4X expressions can frequently become polluted with [0]s. Alternately, you can just place one at the end of a chain of filters. 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 an XHTML document this way. The result of this query is:
<age>27</age> <age>26</age>

We didn't bother to look for the <person> tags; those <age> tags can come from anywhere in the XML.
thePeople.*.age

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 doesn't care what the first generation child is, as long as the second generation child is <age>

Strings and XML


When you're printing out XML elements, if you don't specify a different 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:

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 3 de 17

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>

[0].@name

You can use the text() filter to grab text nodes out of XML. For instance, grabbing an attribute like thePeople.person 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:
trace(thePeople..age.text()); //2726

Note that toString() doesn't add any space. toXMLString() does, but since they're both text nodes, it prints out as:
27 26

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.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. It's 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 child(name), children()

These axes find the children of the given node[s]; by child I mean a first-generation descendent. The first finds a child of a specific name, and is the same as typing that name in literally. The second finds all children, which we've seen before as the asterisk operator. The following holds true:
thePeople.child("*") == thePeople.children() == thePeople.*

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 4 de 17

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 node's parent or nodeset's 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 what's 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 node.parent().*[node.childIndex() + 1]; //next sibling node.parent().*[node.childIndex() - 1]; //previous sibling

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 aren't 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 "processinginstruction." Note also that processing instructions and comments are typically ignored unless you change those settings on the XML object. The elements(), comments(), text(), and processingInstructions() axes select nodes of these types as children.

Creating and Updating Values


When you select nodes with a filter chain, you'll 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 we've 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"];

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 5 de 17

var newPerson:XML = <person name={names[int(Math.random() * names.length)]}> {newAge} </person>;

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!

I'm not sure why the last line doesn't 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 don't 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
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. There's one odd addition to the language that's specified in the E4X spec, and that's 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

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 6 de 17

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
75% of what you'll need to do with E4X is simple, but there are a bunch of gotchas, and I think it's not doing AS3 any favors to try to gloss this over. I'm 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 filtering when we have existing languages such as XPath and the Selectors API is that they are too difficult to learn, and not "simple" enough. I'm certainly happy that there's some native XML support in AS3, but let's 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.

62 Responses to AS3 E4X Rundown


1. Createage .com Good E4X Info from Roger Says:
May 21st, 2007 at 8:21 pm

[] http://www.partlyhuman.com/blog/roger/as3-e4x-rundown [] 2. VT Says:
May 21st, 2007 at 8:44 pm

Thanks for the post. I cant wait to work with XML using E4X! 3. diamondTearz Says:
May 22nd, 2007 at 1:06 am

Im glad to see someone put in writing that E4X is just not that simple. Its a better way of doing things but there are certain things about it that one would not just figure out. 4. bobbaganoosh Says:
May 23rd, 2007 at 8:27 am

yes, thank you- im in the same situation and all the docs ive ever seen just say that e4x is so darn easy that it seems a good explanation is not necessary. even some of the newer flex books dont even talk about e4x, still doing things the old way. ive struggled with that stuff for days- your post is a big help. 5. Stefan Says:
May 24th, 2007 at 7:33 am

Thanks, and a possible useful addition: When using soap you have to switch to the correct name space, it will not work if you dont: private namespace wtf = http://bla.com; use namespace wtf;

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 7 de 17

6. Roger Braunstein Says:


May 24th, 2007 at 4:01 pm

@Stefan, thanks! I will post more about namespaces in a bit, I was getting tired of typing and I covered it a little bit in the linked article ;) Ill stop being lazy though. Hehe. 7. moca Says:
May 28th, 2007 at 7:27 am

This is great, thanks a lot! But what about something like this? This is my xml:
<list> <month month="3" year="2007"> <day date="01" impressions="407"/> etc... </month> <month month="4" year="2007"> etc... <day date="30" impressions="657"/> </month> </list>

More months will be added with time so I need to set a variable always with the values of the lastest month: endDate = new Date(2007,5,30) Accessing the beginning of the month is easy enough: startDate = new Date(xml.month[0].@year,xml.month[0].@month,xml.month[0].day[0].@date); But how to get to the last node attributes if the last mode is constantly changing? 8. Roger Braunstein Says:
May 29th, 2007 at 12:36 am

Hey Moca, This code could go through all of the entries in order:
for each (var month:XML in xml.month) { for each (var day:XML in month.day) { var d:Date = new Date(month.@year, month.@month - 1, day.@date); trace(day.@impressions + " impressions on " + d); } }

Or this takes the last one:


xml..day[xml..day.length() - 1];

9. moca Says:
May 29th, 2007 at 6:06 pm

xml..day[xml..day.length() - 1]; Is what I was looking for.. Thanks a lot! 10. Jeff Says:
June 1st, 2007 at 12:56 pm

Badass! 11. Jim Kremens Says:


June 9th, 2007 at 12:20 am

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 8 de 17

Ive come across another annoying issue that you briefly alluded to - the weird typing of attributes in E4X. Heres an example. Starting with your blob of XML above, I added a hatSize attribute. You might expect that attribute to be a string or number when you ask the compiler for its type, but it turns out to be an XMLList!
var thePeople:XML = 27 Mims H Wright Teh AWesoeomes! rulz<b>!]]> var hatSize:XMLList = thePeople.person[0].attribute("hatSize"); trace(hatSize, hatSize is XMLList, hatSize + 1, Number(hatSize) + 1);

So, the number 8 is an XML List Makes perfect sense! :-) I think its important to be able to know the type of an attribute value. I often work with externally loaded data where the attributes look something like this:
colors="[0x666666, 0xFFFFFF]" alphas="[100, 100]" ratios="[0, 75]" matrix="{big object here}

In AS2, it was easy to write a routine that would actualize all of those strings, turn them into real objects, and insert them back into the attributes object. Then, when working with the XML, I could be sure that I had a real number, a real array, a real object, or whatever. If you know what youre looking for, like hatSize, this isnt a big deal. You can retrive the value and cast it to number. But say, for example, that youre using a hybrid of JSON and XML and you want to use the JSON objects to configure some class? In that case, you dont know what youre looking for - you just want to throw the JSON at the class for configuration purposes. It was possible to convert attributes and node values into real objects (from strings) in AS2, but doesnt seem to be possible in AS3/ E4X. I hope Im wrong Any ideas? Thanks for the great post [ed: I tried to format your XML so that wordpress doesnt eat it, but I might still be missing some] 12. Roger Braunstein Says:
June 11th, 2007 at 2:59 am

Hey Jim, No, theres no way for E4X to divine what kind of data is stored in attributes or text nodes. This is certainly one weakness of the format. Typically, though, XML is used in some well-defined communication a contract where the parties agree on what format to speak in; in most cases, youll know that the hatSize attribute is meant to be a number. Exchanging an XML schema or talking in a further defined language like SOAP can ensure that your program knows what the mapping should be like. However, when it comes down to it, you still have to convert everything from strings. If you typed things in JSON-style, like your colors or alphas or ratios variables, you used to be able to eval() them to interpret them as the AS2 interpreter would as code. However, eval() is not available in AS3. You can use code from the JSON library in Adobe Labs core library to do that work for you. 13. Jim Kremens Says:
June 11th, 2007 at 2:23 pm

Hi Roger, Thanks for the reply You can use code from the JSON library in Adobe Labs core library to do that work for you Thats what Im doing (with some modifications). The problem Im having is one of workflow. In AS2 I was able to pull in a piece of XML, turn all of the values from strings into real values using a JSON parser, then store those real values back in the same XML. Because I was able to do this, I did. But now it strikes me as perhaps not the best practice. Funny, that. It is indeed a limitation of the format, but I think the answer is for me to rewrite this particular section of code so it doesnt rely on specious coding practices

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 9 de 17

Thanks again, Jim 14. Nebulan Says:


June 12th, 2007 at 12:59 pm

Hi, Ive been struggling with generating a graph in Flash using data from an XML file. My problem is that Im looping through the XML with a for-loop but anymore than 500 iterations before Flash times out. Its definitely this statement thats slowingdispatchEvent AS3 E4X Rundown things down: tmpTime=eventXML.event[n].time; Its the only access to the XML in the loop. Is E4X less time efficient than AS2s XML classes or is it just impossible for me to parse a 60,000 entry xml file in flash? Perhaps if I broke up the xml into multiple files? 15. Alex Says:
June 12th, 2007 at 10:49 pm

Ok, maybe I dont understand the plusses just yet so I wont condemn Flash CS3 as a whole, but I really do not get why I am no longer able to create an XML object by loading a string of XML. Im trying to create a new XML object and what I have to create it with is a string like Dinkie32. Can anyone tell me how I can go about getting this done? Thanks for any help! 16. Rian fowler Says:
June 25th, 2007 at 12:43 pm

You say that you can delete an XML list with the delete operator but I am unable to do that in Flex Builder 2. I get a run time error #1119: Delete operator is not supported with operand of type XMLList. Is there a way to delete the results of an e4x query? 17. Roger Braunstein Says:
June 25th, 2007 at 1:42 pm

@Rian, no, Im afraid you cant filter out some nodes into an XMLList and then delete all these nodes from the source with one delete command. AS3 thinks this is trying to delete the local XMLList variable, not the nodes from the original XML. Good call, this is pretty irritating. Im trying to think of a clever way around it but coming up short. Even if you stepped through all the XML nodes, it would think youre trying to delete the local XML variables. Damn. 18. Roger Braunstein Says:
June 25th, 2007 at 1:56 pm

@Alex, you should be able to create XML from a string by calling the top-level XML() function on it. This function looks like a cast but is a conversion.
var xml:XML = XML("<test>testing</test>");

19. Roger Braunstein Says:


June 25th, 2007 at 2:02 pm

@Nebulan, just remember that executing a complex string of filters can take a lot of time. Your expression is not that complex, but, the expression
eventXML.event[n].time;

will be evaluated in each iteration of the loop. This means that every iteration youre going to look through the entire xml for all child nodes named event, and then find the nth. I bet you could get a serious speedup by calculating the list of possible event nodes first:
var events:XMLList = eventXML.event; for (var i:int = 0; i < events.length(); i++) { var time = events[i].time; }

I bet this will run a lot faster. Just remember to minimize the work you do in each iteration. 20. farz Says:
June 26th, 2007 at 7:19 am

thank u so much, great overview, im having trouble importing external XML files and setting them into a XML List Var :(

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 10 de 17

21. BenH Says:


June 26th, 2007 at 9:58 am

Great overview - thanks Roger. Im still struggling though as Ive got some awkwardly structured XML (which I cant change) which Im trying to output to screen in human readable form. One node looks like this;
<TextFeed id="150" correction="No" normalTime="90:00" addedTime="2:24" lang="en-GB" xmlns="http://www.w3.org/XML/1998/namespace"> Attacking throw-in by <Player id="193562"> <Name>Fitz Hall</Name> </Player> <Team id="68">(Wigan)</Team> . </TextFeed>

I would like to be able to output something like;


<p>Attacking throw-in by <span class="player">Fitz Hall</span> <span class="team">(Wigan)</span>.

Would really appreciate any help on that you can offer 22. Roger Braunstein Says:
June 26th, 2007 at 10:57 am

@farz, I added a section about loading external data. I hope this helps! 23. Danny Patterson Says:
June 26th, 2007 at 9:43 pm

Great post Roger. I agree that E4X is not necessarily easy, but it certainly is better than anything we had in AS2. 24. farz Says:
June 27th, 2007 at 1:11 pm

thank you very much for such a quick reply, i ended up using HTTPSERVICE. hope u dont mind if i post it here, in case someone is also looking for an alternative //script import mx.rpc.events.*; [Bindable] private var dataDetails:XMLList; private function dataHandler(evt:ResultEvent):void {dataDetails= evt.result.person;} //script 25. Brian Ferris Says:
June 30th, 2007 at 7:36 pm

Hey Roger Unlike Dannys comment-Ive been wrestling with a problem that I think was easier to solve in AS2-I was wondering what your take was. I think error reporting is actually worse in AS3. Or to be precise, while built in error reporting is better in AS3; your ability to track down problems in your XML is actually less. See http://www.webdevelopmentcentral.net/2006/11/xml-error-reporting-as2-trumps-as3.html for the gory blow-by-blow; but in essence, in AS2 you can track down errors to the originating node or even the originating line in an XML file; I cant seem to figure out a way to do this with e4X. Any ideas? Perhaps Im struggling with Adobes implementation more than I am with e4x itself. 26. Roger Braunstein Says:
July 1st, 2007 at 6:41 pm

@Brian, I think that you are right in that AS3 is very unforgiving of malformed XML. You would be much better off verifying the validity of input XML in a separate environment, like a server script. I havent had much experience with trying to cope with malformed XML in AS3 yet so I am inclined to believe what you say :) 27. Jaxim Says:

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 11 de 17

July 2nd, 2007 at 12:20 pm

Question: When I attempt to use the double dot syntax (thePeople..age) in Flex/Eclipse, it throws an error. Is this syntax exclusive to Flash CS3? What is this the source of this info? I cant find the double dot syntax mentioned anywhere in the help Flash CS3 files. 28. Brian Ferris Says:
July 2nd, 2007 at 12:22 pm

Thanks anyway. I dont mind AS3 being unforgiving about XML problems-I just wish it would do a better job at telling us where problems lie so we can handle unforseen conditions programmatically. 29. Jaxim Says:
July 2nd, 2007 at 12:31 pm

I just discovered that Adobe refers to the double dot syntax as descendant accessor, which is mentioned in the Flash/Flex help files. However, I am still uncertain as to why using the descendant accessor causes problems in Flex. Anyone? 30. Roger Braunstein Says:
July 2nd, 2007 at 1:53 pm

@Jaxim, can you be more specific about your code and the error? Flex is fine with using the descendant accessor. Are you getting a runtime error or compile time? What error? It could be that your XML is invalid or null, or a type error, or something else. 31. Jaxim Says:
July 2nd, 2007 at 2:18 pm

Ive narrowed down what Im doing wrong. It has to do with how I am calling the operator. Using the above example, I am attempting to do the following: thePeople..(age >= 21) Is this even possible, or do I need to call a node name after I use the descendant accessor? i.e. thePeople..person.(age >= 21) Is one way of doing what I want to do by using the descendant method: i.e. thePeople.descendant(*).(age >= 21) 32. Roger Braunstein Says:
July 2nd, 2007 at 3:47 pm

@Jaxim, yes, filters like (age >= 21) must apply to an existing XMLList. They reduce the amount of matching nodes without descending into them. Axes like parent(), descendant(), child() actually change the location. When you say
thePeople..(age >= 21)

Youre kind of saying descend into age greater than 21. The words that are missing are descend into nodes whose age is greater than 21. First you descend, then you filter.
thePeople..*.(age >= 21)

Furthermore, not all descendant nodes have children called age so you could have a problem with that, and its also a good idea to tell the compiler how to compare that age; the way its written above, it tries to compare an XML node to an int. To avoid ambiguous decisions by the compiler, let it know how to do the comparison.
thePeople..person.(parseInt(age.toString()) >= 21)

This is much more precise. Hope this makes sense! 33. Jaxim Says:
July 2nd, 2007 at 4:48 pm

Thanks, Roger. So are you saying the following line would work: thePeople..*.(age >= 21) As far as (age >= 21), I agree with your suggestion, but I was only using the example you had previously used in your post. If it helps reduce matters, let me know if the following line would work to find all the nodes (regardless where they are in the XML) that have an aka child node equal to Rog:

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 12 de 17

thePeople..*.(aka == Rog) 34. matias Says:


July 10th, 2007 at 6:21 pm

Hi im new in E4X in ActionScript 3.0 , and i have one question if you could please answer me : This is my example: And de XML file is: My question: In RunTime this program , when you click a button MATO , the nopde month=March chance to month=MATO , its OK! But this node not change in the sampleData.xml why??? 35. Jaxim Says:
July 27th, 2007 at 11:19 am

If you use an expression to find a value, make sure the expression is applicable to all of the nodes or else you will get an error. For example, let me use the following XML example so one of the nodes does NOT have an "id" attribute: <order> <item> <menuName>burger</menuName> <price>3.95</price> </item> <item id=2> <menuName>fries</menuName> <price>1.45</price> </item></order> The following line would then produce an error and NOT output "fries" trace(myXML.item.(@id==2).menuName); Error produced ReferenceError: Error #1065: Variable @id is not defined. You would think that since the first "item" doies not have an ID, the above trace statement would ignore the first node and find the node where (@id ==2), but thats not the case. Becasue the 1st "item" does not have an id, it produces an error. It would seem that all "item"s would require the "id" attribute for the expression to work. If anyone knows of a workaround for this problem, please respond. 36. Roger Braunstein Says:
August 22nd, 2007 at 3:22 am

Josh Tynjala has a sweet set of E4X articles: ett tv tre 37. Roger Braunstein Says:
August 22nd, 2007 at 3:23 am

Btw, @Jaxim, the workaround is to use attribute(foo) rather than @foo. 38. Colin Says:
September 30th, 2007 at 2:03 pm

thanks for the article does flex or e4x provide any functions for sorting XML data, Im populating a Tree but the data needs sorting, any help would be appreciated.

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 13 de 17

39. Jim Freer Says:


October 3rd, 2007 at 9:49 pm

I have several posts on sorting XML data for trees. The most recent: http://freerpad.blogspot.com/2007/07/morehierarchical-sorting-e4x-xml-for.html 40. Roger Braunstein Says:
October 4th, 2007 at 12:08 am

@Jim, good info, thanks for the link! 41. Donovan Adams Says:
October 14th, 2007 at 7:44 pm

Great post Roger! I kinda wish Adobe would have switched the length property of an Array from a getter to a regular method thanks to the length function of XMLList. You should consider a post on the use of XML namespace and how useful and powerful it is:) BTW, I took over J. Buzzeos spot over at SciFi when you did the Triangle site;) I also did the last years mini site with Moses. Small world! :) 42. 739 Saint Louis St Blog Archive Rusty e4x? Good reference links to help you brush up. Says:
October 17th, 2007 at 10:14 am

[] http://www.partlyhuman.com/blog/roger/as3-e4x-rundown [] 43. the bitmechanic Blog Archive Flex - first impressions Says:
October 21st, 2007 at 11:22 pm

[] I dont understand XML namespaces at all. I banged my head against some e4x namespace issues for about 2-3 hours (this post was very helpful). [] 44. Alexandre Conrad Says:
October 26th, 2007 at 5:36 am

I started monkey patching the XML object to have more convient functions for XML tree traversal. This combined with the current E4X API should pretty much fill some gap.
// Implement new methods to the XML class XML.prototype.isDocumentElement = function():Boolean { if (this.parent() === undefined) { return true; } return false; } XML.prototype.nextSibling = function() { if (this.parent() === undefined) { return undefined; } return this.parent().elements()[this.childIndex() + 1]; } XML.prototype.previousSibling = function() { if (this.parent() === undefined) { return undefined; } return this.parent().elements()[this.childIndex() - 1]; } XML.prototype.firstElement = function() { return this.elements()[0]; } XML.prototype.lastElement = function() { return this.elements()[this.elements().length() - 1]; } XML.prototype.isFirstElement = function():Boolean { if (this.isDocumentElement()) { return true; }

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 14 de 17

if (this.parent().firstElement() === this) { return true; } return false; } XML.prototype.isLastElement = function():Boolean { if (this.isDocumentElement()) { return true; } if (this.parent().lastElement() === this) { return true; } return false; } ////////////////////////////////////////

Regards, Alexandre Conrad 45. Mark Serrano Says:


November 13th, 2007 at 4:47 am

Excellent article. This should help E4X newcomers. I believe E4X is much simpler than the old AS2 XML implementation but what makes E4X difficult is the LACK of samples and documentation, unlike the old AS2 XML the examples are numerous. How about XMLListCollection? Ive managed to store HTTPService result to an XMLListCollection, edit and send it to another HTTPService. Are there any tips and caveats with XMLListCollection that you or any of you know of? 46. Metal Hurlant Says:
November 15th, 2007 at 10:25 pm

Another fun tidbit about the as3 XML object: It can be used to represent graphs that go beyond simple trees. In fact, any non-cyclical graph can be represented with XML objects. The downside is, the .parent() method becomes a lot less useful, since it will only point to the *last* parent the node was added to, cutting out any way to access the other parents a node may have. In general, I agree that E4X looks deceptively simple. Just like XML itself, in many ways. 47. Sekati Labs Archive AS3 + E4X Resources Says:
November 17th, 2007 at 8:23 pm

[] friend Roger has written an in-depth article covering AS3 and E4X over at DispatchEvent which is quickly turning into a very lively dialogue. He has also made the [] 48. matt eisenberg Says:
November 27th, 2007 at 9:15 am

Wow thanks - this is like the missing manual for e4x! Hey adobe - give this guy an ipod or something! 49. David Frankson Says:
November 27th, 2007 at 2:18 pm

In case someone else needs to do this, lets say you have some XML: var sample:XML = <root> <parent1> <child1/> </parent1> <parent2> <child2/> </parent2> </root>; And lets say you have a complex string that has the e4x path you want: var path:String = parent2.child2;

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 15 de 17

sample.descendants(path); will not work, it doesnt like . path notation even though * will hit all descendants. If this functionality is supported, does anyeone know the proper syntax? Anyway, I found a simple library that can do this: http://www.adobe.com/devnet/flex/articles/e4x.html with the statement: E4XParser.evaluate(sample, path); 50. .COM Says:
November 27th, 2007 at 9:03 pm

AS3 E4X Rundown By Roger Braunstein | on May 21, 2007 51. devon Says:
November 29th, 2007 at 10:13 pm

@Rian et all Re: #1119: Delete operator is not supported with operand of type XMLList I have struggled and suffered here alsobest I can figure is to access elements of the dynamically created XMLList via array index, ie:
delete XML_nodes.term.(@tid == e.element.@tid)[0];

52. moses gunesch Says:


January 26th, 2008 at 3:45 pm

Roger, this is a great post. It almost answered my question which took a lot of googling to find. The answer came from Peter Hall at a forum thread here: http://groups.google.com/group/xpath-as3/browse_thread/thread/7929b1384b6bcc5b. The question (what is this, jeopardy?) was how to replace the text value of a node, which turns out to be absurdly complicated or maybe noone knows the official way, including the Flash documentation. Here is peters solution which works great, although i am not sure why e4x would make something normal into a crazy reach-around workaround node.parent().children()[node.childIndex()] = blah; I would suggest adding a section to your post on replacing nodes and content, not just for this hack but also the official replace methods. (Pardon my griping but those methods are badly documented and seem relatively worthless.) 53. Sam Goody Says:
January 29th, 2008 at 4:17 pm

It is not accepting variables ({}) in external e4x files. Claims it is malformed. Am I the only one with this problem? Is there any solution? My ultimate goal is to get a function name or attribute from the e4x. Since as3 has no eval(), I thought I could pass in an attribute as a variable. eg: in font.xml: in as3 file: var x:XML = new XML(new URLLoader(new URLRequest(font.xml)).data); var t:textFormat = newTextformat(); for(var att:* in x.frmt.attributes) t[att.name()] = att; I hope the above is clear. It claims that align is malformed 54. Roger Braunstein Says:
January 29th, 2008 at 4:27 pm

@Sam, the inline-variable syntax is only valid for XML literals (typed directly into code). Your XML was eaten by Wordpress, try editing your comment and using the link provided above the comments. Also, you know that you cant load a file like that right? You have to wait for the URLLoader to complete loading before you can access the data property. 55. Roger Braunstein Says:

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 16 de 17

January 29th, 2008 at 4:31 pm

@Moses, yes, theres a very subtle difference between modifying existing nodes and replacing nodes. Most of the ways you modify data in E4X replacing nodes. Also, the problem youre running into is that, in order to replace nodes, you have to do that from an outside perspective. You cant just shoot at yourself, you have to stand up on a ledge so you can see what you wanna shoot and then shoot. Weird analogy. So thats why you have that awkward syntax which jumps up and then finds its way back down. Its a good idea, having a section on replacing and modifying data. I should add that. 56. Sam Goody Says:
January 31st, 2008 at 3:24 am

@Roger - Re:My last post 1) I know how to load xml, just wanted the comment to be clean. How do I post without Wordpress eating my tags? 2) XML is first and foremost an interchange language: a way that php, flash, aspx, and more could communicate with a common tongue. If you cant use the power of e4x in external files, that kinda turns it into a vaporware. It is much more likely to have your example file above coming from a database (created by people.php) than residing in the flash file itself!! And if the abilities are going to be limited (I also had a problem with external CDATA), let there be clear documentation about the limitations. If you could add it, I think this article is already the semi-official docs ;) 3) I guess the real gripe I have is Adobe dropping eval(). If it was still there, I would be able to evaluate the xml and get my variables and cdata. I also would be able to store the reference to a function inside the xml (func)function1(/func) which I cannot figure out any way of doing now. And to store unencoded urls, etc. 3) I tried to put comments into the external URL using /* */. It balked. Is that becuase external e4x doesnt handle comments, or are comments left with a different format? 4) Thanks for the great work 57. Roger Braunstein Says:
January 31st, 2008 at 1:49 pm

@Sam: 1. Please use the link provided above the comments thread to encode xml for comments. 2. Well XML is the interchange language. E4X is a programming tool. Nobodys going to change the way XML works for E4X. The {} syntax is a convenient shortcut for creating XML inline its not part of XML. When you load in an XML file with Flash, it had better treat that XML just like everyone else in the world treats XML or it wont be very good at its job. I did coincidentally run into some problems with CDATA, so Id like to add a section on that, indeed. 3. The thing is, AS3 gets its speed from being compiled to a bytecode and then being interpreted by the AVM or even interpreted further into machine code, which all executes way closer to the speed of native applications. That means for you to be able to eval() things, each persons copy of Flash Player would also have to have a full compiler for AS3. This would make Flash Player much bigger to download which goes against one of Adobes big priorities with the Flash Player platform. Furthermore, eval() would bring in a lot of interesting and strange exceptions to think about in terms of application context, security sandbox, compile-time errors in runtime code 3.5. Comments in XML must be typed in <! this kind of tag > 4. Thanks for making it better with your comments! 58. Roger Braunstein Says:
February 1st, 2008 at 12:59 am

E4X: Beginner to Advanced, another great E4X article by Josh Tynjala @ Yahoo! 59. Andrew Says:
February 5th, 2008 at 1:08 pm

Sorry if I missed this in here if someone already pointed out a technique. What would be the best approach for swapping positions of nodes in an xmllist? 60. Andrew Says:
February 5th, 2008 at 3:06 pm

http://mimswright.com/blog/?p=141

15/02/2008

AS3 E4X Rundown | dispatchEvent

Pgina 17 de 17

Well, I got it to work (swapping nodes) but can anyone explain this? This works: clone = blogs.blog[delNum]; delete blogs.blog[delNum]; blogs.insertChildBefore(blogs.blog[delNum-1],clone); This does not: clone = blogs.blog[delNum]; blogs.insertChildBefore(blogs.blog[delNum-1],clone); delete blogs.blog[delNum]; For both the above delNum is derived from the dataProvider the XMLList generated. ie: var delNum:Number = blogs_cb.selectedIndex Sorry if this was obvious but Deleting the node after doing a insertChildBefore was not working for me. I had to use the clone to hold the node while I deleted its original before inserting. If there is a better way.? 61. allika Says:
February 7th, 2008 at 3:22 am

Is TTS Engine(Text-To-Speech),an inbuilt feature of AS3 62. Mims Wright Says:


February 8th, 2008 at 4:15 pm

@allika TTS is NOT a built-in feature of AS3. If anyone knows of a TTS implementation, let us know!

Leave a Reply
Name (required) Mail (will not be published) (required) Website

Anti-spam word: (Required)*


To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.

Submit Comment

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

http://mimswright.com/blog/?p=141

15/02/2008

Vous aimerez peut-être aussi