views:

524

answers:

3

Hi!

XML is cool in flex, but I have an annoying problem to solve, caused by what I can imagine is a feature. You see, when you have just one tag of something, it creates an object which is not an array. But when finds more than one, it puts it on an array structure.

I want to solve it elegantly. Any recommendation.

Example: this illustrates it, being the result of a HTTP request:

private function initXMLRes(event:ResultEvent):void
{
    var resObj:Object = event.result;
    //
    for each(var i:Object in resObj.specifictag)
    {
        // to use specifictag attributes, etc. example:
        Alert.show(specifictag.name);
    }
}

The code before will work with 2+ items. It will accept this xml:

<specifictag name="one" /><specifictag name="two" />

... but not this one:

<specifictag name="one" />

I could check the format of resObj.specifictag (to check if it is has an array) and then duplicate the code (for each case). But -even if it's calling a function- I don't think it is an elegant solution.

Well, I hope someone has a good idea on this matter. (I know from experience that SO has much more C++ experts than flex, but well...)

The perfect thing would be that HTTPrequest handled every tag in a consistent way (using always arrays... though I'm guessing that that would also have its drawbacks).

Thanks!

+1  A: 

The problem I think is actually a bug, that you can handle in your HTTPService result handler and force your returned object into being an array collection. Here's a snippet from my app.

if (evt.result.rows.row is ArrayCollection) {
    MyAC= evt.result.rows.row;
}else{
    MyAC= new ArrayCollection(ArrayUtil.toArray(evt.result.rows.row));
}

So it should work for you like this:

var resObj:Object = new Object();

if (event.result.rows.row is ArrayCollection) {
    resObj= event.result
}else{
    resObj= new ArrayCollection(ArrayUtil.toArray(event.result));
}
invertedSpear
Well, I ended up with a similar solution, but I like your code snippet much more. :D
huff
A: 

This is my current solution:

// historial
var hist:ArrayCollection = new ArrayCollection();
if(resObj.hist[0])
  hist = resObj.hist;
else
  hist.addItem(resObj.hist);
huff
A: 

It sounds like your <specifictag> elements are top-level and not inside some other root? An XML document can only have one root, so in this case you're actually getting an XML document in some cases and an ArrayCollection of XML documents in other cases. If you change the service to always return a single XML container which has specifictag as it's children, you won't have to worry about this problem.

The following code demonstrates that iterating over one element works the same as iterating over multiple when dealing with XML objects.

private function init():void {
    trace("Iterating two children");
    iterate(<root><child /><child /></root>);
    trace("Iterating one child:");
    iterate(<root><child /></root>);
}

private function iterate(x:XML):void {

    for each(var element:XML in x.child) {
        trace(element.name());
    }
}
Sam
No, they're at the root of the XML... I will try to put under a root tag, to see if they're considered an ArrayCollection there. Thx!
huff
It doesn't work either, doesn't matter where they are positioned.
huff