views:

586

answers:

4

I can't help think that making XML ad XMLList both unrelated, as in both extend Object directly, is a design flaw in the AS3 core library. Surely having XML extend XMLList would be a much cleaner system, where XML is considered an XMLList with only one member?

This would also avoid the very annoying practice of an E4X query possibly returning either an XML or XMLList, which can result in a casting error.

So is there any reason I'm not thinking of that XML and XMLList were designed to only have Object as a common type?

+2  A: 

It seems that according to the ECMA spec for E4X (p22) and the XMLList documentation, that the XMLList class does contain the methods of the XML class, but only when there is one member. So when performing an E4X query the result should always be stored in a variable of type XMLList.

Beforehand, due to the naming of these objects, I presumed that an XML object represented a complex tree of XML element data, but according to the spec(p12), this is not true, "Each value of type XML represents an XML element, attribute, comment, processing-instruction or text node".

It is the XMLList class that should be used as the more generic type of the two: "A value of type XMLList represents an XML document, XML fragment or an arbitrary collection of XML objects (e.g., a query result)"

So this solves my casting issue, as I should have never stored E4X queries as a variable of type XML. I should only use the XML class for iterating over XMLLists and breaking apart XML elements.

Brian Heylin
A: 

So my concise answer to this question is that, it seems, from looking at the inheritance tree that, yes the two classes (XMLList, XML) are unrelated.

But, from looking at the ECMA script/AS3 documentation, that they are related, most likely using the prototype system of ECMA script/AS3.

When an XMLList has only one member it can be treated like an XML node. I presume that the methods and fields of the XML class are inserted into the XMLList prototype by the AVM2.

Brian Heylin
A: 

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]);
Niko Nyman
A: 

In ActionScript 3.0 XMLList is the new way to handle xml where as the XML class is an AS 2 thing so it was include to provide backwards compatibility.

If your writing new code you should be using the XMLList now.

Hope this helps

Jon

Jon
Hey Jon, I have no confusion over the XML class taken over from AS2, The confusion was that there exists an XMLList and and XML class in the AS3 core lib. The relationship between these was a confusing to me. I see this as a case of bad naming, you can see my answer up the top
Brian Heylin