As you have noticed, the automatically changing XML and XMLList types can get quite confusing. Such things happen when clever programmers (pointing to Adobe here..) make convenience wrappers around things.
What's going on is an "automatic type conversion" of sorts. And it doesn't stop to the XML type. Consider this example XML:
<myXml>
<sound id="0">Boogaloo</sound>
<sound id="1">Bond theme</sound>
<sound id="2">2001</sound>
</myXml>
Let's say I have the above XML in a variable called myXml
. In the following example the E4X returns an XMLList with one item, and we access the first XML item using [0]
:
trace(myXml.sound.(@id == 0)[0] == <sound id="0">Boogaloo</sound>);
// traces true
In this example we leave out the [0]
part, relying on the automatic type conversion of Flash. The one returned item is converted to XML:
trace(myXml.sound.(@id == 0) == <sound id="0">Boogaloo</sound>);
// traces true
But in cases where this one matched XML node contains a simple text node, Flash automatically converts the type even further into a String:
trace(myXml.sound.(@id == 0) == "Boogaloo");
// traces true
And if the text node can be interpreted as a number (XML node with id 2), Flash converts it even further into a Number!
trace(myXml.sound.(@id == 2) == 2001);
// traces true
Woot!
So, what to do about this?
As you have noticed, you have to be very careful with types and the "convenient" XML handling. One suggested practice is to always use the array access operator to point to the first XML item of an E4X result, when you know you want a single result:
config.users.admin[0].settings[0].email.(@type == "work")[0];
It looks weird at first, and adds verbosity to the code, but the benefit is that you're explicitly saying that you're looking for one admin
element, one settings
element, and one email
element of type "work"
. And you get used to the look of it.
Another tip is to always remember to cast to the type you're expecting to use. Some examples:
allUsers = XMLList(config.users);
adminSettings = XML(config.users.admin[0].settings[0]);
adminWorkEmail = String(config.users.admin[0].settings[0].email.(@type == "work")[0]);
adminBirthYear = int(config.users.admin[0].birthdate[0].@year[0]);