How can I convert a simple XMLList to an Array of Strings without a loop?

27.1k Views Asked by At

How can I convert the following XMLList to an Array of Strings without using a loop?

<labels>
    <label>All</label>
    <label>your</label>
    <label>base</label>
    <label>are</label>
    <label>belong</label>
    <label>to</label>
    <label>us.</label>
</labels>

I want this result:

["All","your","base","are","belong","to","us."]

Right now, I am doing the following:

var labelsArray:Array /* of String */ = [];

for each (var labelText:String in labels.label)
{
    labelsArray.push(labelText);
}

I was wondering if there is a simpler way to do this in ActionScript 3.0

6

There are 6 best solutions below

1
On

i feel like there's a one-liner for this out there somewhere... oh well.

question: why does .length fail here? (always 0)

 public static function xmlListToArray($x:XMLList):Array {
        var t:int = $x.length;
        var a:Array=new Array(t), i:int;
        for (i = 0; i < t; ++i) a[i] = $x[i];
        return a;
    }
0
On

This one works pretty well:

public static function xmlListToArray($x:XMLList):Array {           
    var a:Array=[], i:String;
    for (i in $x) a[i] = $x[i];
    return a;
}
1
On

This works good but uses some odd syntax of the XMLList. The last statement can be placed on one line if desired.

    var labels:XML = <labels>
                    <label>All</label>
                    <label>your</label>
                    <label>base</label>
                    <label>are</label>
                    <label>belong</label>
                    <label>to</label>
                    <label>us.</label>
                </labels>;

var labelsArray:Array /* of String */ = [];

labels.label.
(
              labelsArray.push(toString())
);  

The toString() call can be replaced with an attribute() call to pull out attributes.

10
On

for loops are extremely fast in AS. Why'd you need that? But you could give this a try:

private function toArray():void {
    var xml:XML = <labels>
               <label>all</label>
               <label>your</label>
              </labels>;

    var array:* = xml.label.text().toXMLString().split("\n") ;
    trace(array as Array);
}
0
On

Your current implementation is more than sufficient. The only optimisation you could make (though I wouldn't bother unless you are using Vector.<>) is to pass in the initial capacity into the Array constructor:

var xmlLabels : XMLList = labels.label;
var labelsArray:Array /* of String */ = new Array(xmlLabels.length);

var index : int = 0;

for each (var labelText:String in xmlLabels)
{
    labelsArray[index++] = labelText;
}
1
On

Despite the earnest uses of for loops and logically working on the XML object as given, this is a job for XMLList.
It would best look something like this:

var xml:XML = 
<labels>
    <label>All</label>
    <label>your</label>
    <label>base</label>
    <label>are</label>
    <label>belong</label>
    <label>to</label>
    <label>us.</label>
</labels>
;
var list:XMLList = xml.label;
var labels:XMLList = list.text(); //Optional
trace(list[0]);
trace(list[3]);
trace(list[6]);

This would output:

All
are
us.

I've confirmed this in flash myself. Personally it makes sense to me to use the optional line, and reference labels[0] etc. but that's not needed here.

I know you're asking for an array of strings as the output, but basically I'm asking you why you can't just use the array accessors of an XMLList object.

Here's a fine walk-through on that: Senocular on E4X.