Johnvh.com - home of Dallas, Texas based Flash Developer and web enthusiast John Van Horn

Online home of John Van Horn

E4x and as3 gotcha

I love E4X in AS3. It's powerful and fairly simple. If you haven't worked with it yet, check out Roger Braunstein's excellent tutorial. But I was recently annoyed by this gotcha when doing some xml combining. Let's say you have this:

XML:
  1. <xml>
  2.     <people>
  3.         <person id="123">
  4.             <name>John</name>
  5.         </person>
  6.         <person>
  7.             <name>David</name>
  8.         </person>
  9.     </people>
  10. </xml>

Let's parse with E4X:

Actionscript:
  1. // #1
  2. trace( xml.people.person.length() );
  3. // 2
  4.  
  5. // #2
  6. // no animals, but e4x still returns an XMLList
  7. trace( xml.people.animal.length() );
  8. // 0
  9.  
  10. // #3
  11. // no animals, so no further children, but still returns XMList
  12. trace( xml.people.animal.fur.color.length() );
  13. // 0
  14.  
  15. // #4
  16. // gotcha
  17. trace( xml.people.person.( "123" == @id ) );
  18. // thows: ReferenceError: Error #1065: Variable @id is not defined.

The first 3 examples work great. Even though there are no <animal> nodes, E4X still returns an XMLList. Even looking for more siblings under nodes that don't exist works great - it always returns an empty (but valid) XMLList. Always returning an XMLList makes it easy to work with because you can always for-each over the result.

What I don't understand is the 4th example. It fails because not every <person> node has an id attribute. But so what? If you look at the 2nd and 3rd examples, not every <people> node has an <animal> node. So why don't we get the same result - an empty XMLList?

Turns out that there is an easy solution/work-around, that Roger mentions in his tutorial:

Actionscript:
  1. // will error if every person node does not have an id attribute
  2. trace( xml.people.person.( "123" == @id ) );
  3.  
  4. // use this
  5. trace( xml.people.person.( attribute( "id" ) == "123" ).length() );
  6. // 1

A bit wtf, but at least it works like the other examples.

Comments
Leave a reply
  • gizmodo

    Sep 11, 2009 9:55am

    I part of it is common sense. I for one would never do

    xml.people.person.( "123" == @id ), if anything the normal approach would have been xml.people.person.(@id == "123"). Nonetheless, it is worth mentioning. Thanks.

Leave a reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Twitter
Del.icio.us links
» My delicious bookmarks