Mike Morearty
01 Nov 2006

E4X tip: writing expressions to test attributes that may not exist

E4X is an awesome way to work with XML. But one common pitfall is trying to write an expression that tests the value of a particular attribute, when some of the XML nodes may not even have that attribute.

For example, let’s say you have this XML in a variable called albums:

var albums:XML =
<albums>
  <album name="The Dark Side of the Moon" artist="Pink Floyd" year="1973" />
  <album name="Rubber Soul" artist="The Beatles" year="1965" />
</albums>

It’s easy to write an expression to get all albums that were released in the 1970s:

var seventiesAlbums:XMLList = albums.album.(@year >= 1970 && @year <= 1979);

But let’s say some of the XML nodes you are testing don’t have a “year” attribute:

var albums:XML =
<albums>
  <album name="The Dark Side of the Moon" artist="Pink Floyd" year="1973" />
  <album name="Rubber Soul" artist="The Beatles" year="1965" />
  <album name="Haunted" artist="Poe" />
</albums>

In that case, unfortunately the conditional-test part of the above E4X expression, (@year >= 1970 && @year <= 1979), will throw an exception:

ReferenceError: Error #1065: Variable @year is not defined.

So, what to do? I’ve seen various complicated solutions to this problem; but to me the cleanest one is to replace @year with attribute("year") – do this for any attribute that you don’t know for sure will be present:

var seventiesAlbums:XMLList = albums.album.(attribute("year") >= 1970 &&
    attribute("year") <= 1979);

True, this is more verbose and slightly uglier; but it’s not too bad.

The reason this works is that the function XML.attribute() is documented as returning an empty XMLList when the attribute you request does not exist. But when you just say @year, that’s like saying “trace(blah)” where blah is some variable that does not exist – the player tries to find something called @year, and it can’t, so it complains.

comments powered by Disqus