This is one of those things that took me much longer than I thought it would have. I needed to convert a file containing XML data to an ArrayCollection. My XML file looked like this:
<rows> <row> <col1>some value</col1> <col2>another value</col2> ... </row> ... </rows>
I wanted to convert this into an ArrayCollection with each row as an object (and I didn’t want to have to loop through each item in the list). Here’s the solution I’m using.
import mx.utils.ArrayUtil; import mx.rpc.xml.SimpleXMLDecoder; import mx.collections.ArrayCollection; private function convertXmlToArrayCollection( file:String ):ArrayCollection { var xml:XMLDocument = new XMLDocument( file ); var decoder:SimpleXMLDecoder = new SimpleXMLDecoder(); var data:Object = decoder.decodeXML( xml ); var array:Array = ArrayUtil.toArray( data.rows.row ); return new ArrayCollection( array ); }
I’m not thrilled with this approach because I’ve needed to hard code the XML structure (’rows.row’) into the function. If anyone has a better solution I’d love to see it.
Best,
Hillel
It doesnt work!
Rafael,
Do you want to post your code and I’ll see if I can figure out why it isn’t working for you.
I love you 😉 for this article..saved me a lot of time. Thanks
Rahul,
That’s really nice to hear, hoping I might save people time was why I started this blog.
Happy coding!!
Hillel
Hi when i used your code its gives error 1069 and says that rows which is the xml file components in your file is not String value and it does not have default value
what should i do ?
Harsh,
If you’d like to post some example code I’d be happy to take a look to see if I can figure it out.
This error occurs because your xml does not use “rows” and “row” but some other tags. Change your tags to be exactly what appear in your xml, and this will work out fine. For example…
my xml looks like this:
so instead of “data.rows.row” I use “data.merchants.merchant”
Oops! I forgot to make that code so you could see it…
Hi
I’ve tried your solution but I’m getting – TypeError: Error #1034: Type Coercion failed: cannot convert Object@66ea629 to Array.
Code snippet below:
private function convertXmlToArrayCollection( xmlDoc:XMLDocument ):ArrayCollection
{
var decoder:SimpleXMLDecoder = new SimpleXMLDecoder();
var data:Object = decoder.decodeXML( xmlDoc );
var result:ArrayCollection = new ArrayCollection( data.StockQuotes.Stock );
return result;
}
The XML structure is-
some data
some data
I’m using a web service to get the data. I want to bind the data a data grid using an ArrayList.
Thanks for your help.
Hi
Just to let you know, I’ve fixed it by using ArrayUtil.toArray –
var result:ArrayCollection = new ArrayCollection( ArrayUtil.toArray(data.StockQuotes.Stock) );
I’m surprised you weren’t also getting error 1034…..?
Chris,
Hmm.. that’s interesting. I know ActionScript does some fancy stuff when dealing with XML in that it will automatically convert to and from arrays depending on the number of elements. Was there a case where there was only StockQuote or Quote in your dataset. It could be I never got the error b/c all of my tags had at least two elements.
Hi Hillel… Nice tip…
To implement this function in my project… How i can refer the arraycollection returned by function for other components manipulate?
Thanks,
Silva Developer
Silva Developer,
I’m sorry, I’m having trouble understanding what you’re trying to accomplish. Could you please rephrase your question.
Thanks
Hi Hillel
Sorry for taking so long to respond.
Yes, the web service only ever returns one StockQuote with one Stock child.
ie:
<StockQuote>
<Stock>
<Element1>Element 1 data</Element1>
<Element2>Element 2 data</Element2>
etc…
</Stock>
</StockQuote>
Chris,
You’re right, thanks for pointing this out. I’ve updated the post to use your fix.
Thanks!
For me use the arraycollection returned of the function, how i can do this?
For example.
datagrid.dataprovider = ? (name of arraycollection)
The function return an arraycollection, but how i can use this arraycollection returned with other components, referencing by name? what name? Because in the function do you not set the name of this arraycollection will have for use in other components.
If you understanded now, show me in as code.
Best regards,
Silva Developer
silva.developer@gmail.com
To use the value in multiple places, you can store the value returned by the function. Here’s an example
Great… Very good!
One more thing…
If i want use in my mxml file:
< mx:XML id=”_dpStartPositions” source=”positions.xml” format=”e4x” />
And not string var file: = ” Hello “;
How was have do?
Thanks,
Silva Developer
silva.developer@gmail.com
Awesome, happy it was what you needed. You should just be able to pass _dpStartPositions.toString() to the function. Looking at your code though, I’m not sure if you can simply set the source to a file name. Here’s an article explaining how to load an XML file. http://www.flextutor.org/flex-xml/how-to-read-a-local-xml-file-with-flex/
Hi, Hillel!
Thanks for the tip 🙂 It is very helpful for me.
By the way, have you tried to convert ArrayCollection to Xml? I have tried to do this with SimpleXmlEncoder:
public static function convertArrayCollectionToXml(source:ArrayCollection):XML{
var name:QName = new QName(“books”);
var document:XMLDocument = new XMLDocument();
var encoder:SimpleXMLEncoder = new SimpleXMLEncoder(document);
var data:Object = source.source;
var xmlNode:XMLNode = encoder.encodeValue(data, name, document);
var xml:XML = new XML(document.toString());
return xml ;
}
But I don’t like the result. Doing so, I can only specify root name (), but xml children will have name and will look like this:
This not what I want. For me will be perfect if xml will looks like:
I can’t do this with SimpleXmlEncoder, right? I must perform such xml in some other way.
Looking forward to your reply.
Thank you, Christie.
Christina,
I’m sorry, I don’t have any experience using the SimpleXMLEncoder (I actually didn’t even know it existed) and am not sure how to solve your problem. I’d suggest submitting a post to the Adobe Flex forum.
Best,
Hillel
Thank you for such fast answer 🙂 After posting my comment noticed that some text is not showing, sorry, have used tag symbols.. In any case I always can parse my array collection and create each xml child (as string).
With pleasure will follow your blog 🙂
Cheers’O mate. Worked perfect. Reminds me a bit of Generic List’s CovertAll method in .Net.
Christina, nice reversal solution.
Hi! I am doing a memory game in flex. Anyone know how store the images in array? Another problem i faced is how to compare 2 images? I got 16 images with 8 pairs of the same. Example,if image1 is clicked and image 2 is clicked,the image will flipped back because its different. However,if image1 is clicked and another image1 is clicked,both image will stay flipped open.
Anyone can help me? i am really at wits end. Your help will be highly appreciated. Thanks
Shaylee,
I’d suggest posting your question on the Adobe Form
i cannot sign up.There is an error on entering the screen name.
Thanks for your article!
Your sample saves me a lot 🙂
Emilio,
Happy to hear it, thanks for letting me know.
Best,
Hillel
Отлично! Хотелось бы побольше таких же интересных постов
thanks! quick and easy solution worked straight away 🙂
Hi…
and thanks a lot for your excellent article.But, I can’t get it to work! Yet. I guess I am not too far off, so I might just need a bit of help.
I am populating a tree from a remote CFC call. I am getting the following XML back:
<cfquery name="query2" …<cfquery name="query3" …
It works fine if I bind the XML to my tree dataprovider, but I would like to turn it into an Arraycollection for easier manipulation of the tree at runtime.
I have used your function, replacing the rows.row bit with
var array:Array = ArrayUtil.toArray( data.categories.category );
but when I do
treedata=convertXmlToArrayCollection(evt.result);
nothing happens. Any idea, is it to do with my XML structure…?
Thanks in advance,
Alain
Alain,
The problem may be that your using attributes (ie name=”query2″). I’m not sure how the xml decoder handles that. I’d suggest doing a ObjectUtil.toString( ) to see what the data looks like.
Me again. It looks like the CFXML code I posted did not come out correctly on the post. Don’t know why… Let me know how I can post it correctly, or whether I should email it to you directly…
Alain
It doesnt work,
My XML:
João
joao
joao@teste.com.br
(35)3822-3822
Rua X, 99
Blah da Silva
blah
blah@blah.com.br
(35)3822-4900
Rua B, 99
My code to convert:
private function xmlToArrayCollection( file:String ):ArrayCollection {
var xml:XMLDocument = new XMLDocument( file );
var decoder:SimpleXMLDecoder = new SimpleXMLDecoder();
var data:Object = decoder.decodeXML( xml );
var array:Array = ArrayUtil.toArray(data.usuarios.usuario);
return new ArrayCollection( array );
}
It gives error ReferenceError: Error #1069:
Ops,
”
João
joao
joao@teste.com.br
(35)3822-3822
Rua X, 99
Blah da Silva
blah
blah@blah.com.br
(35)3822-4900
Rua B, 99
”
My code to convert:
private function xmlToArrayCollection( file:String ):ArrayCollection {
var xml:XMLDocument = new XMLDocument( file );
var decoder:SimpleXMLDecoder = new SimpleXMLDecoder();
var data:Object = decoder.decodeXML( xml );
var array:Array = ArrayUtil.toArray(data.usuarios.usuario);
return new ArrayCollection( array );
}
It gives error ReferenceError: Error #1069:
Cleiton,
I’m sorry, I can’t see your xml. To prevent wordpress from messing it up, use </> for the angle brackets.
Hello friends,
I’m not understanding what should be given in ArrayUtil.toArray(….);
i want the list of values stored in arraycollection, Error#1009: is displayed. but its not displaying anything. My xml file comng from webservice has huge data with many nested tags. Please help, thanx in adv.
[Bindable]
public var arrcoll:ArrayCollection;
public function GetDataSetHandler(e:ResultEvent):void
{
var xmldoc:XMLDocument = new XMLDocument(e.result.toString());
var decoder:SimpleXMLDecoder = new SimpleXMLDecoder();
var resobj:Object = decoder.decodeXML(xmldoc);
var arr:Array = ArrayUtil.toArray(data.NewDataSet.waiterlocations.locations);
arrcoll = new ArrayCollection(arr);
}
Haneef,
I’d suggest testing the function with a small subset of your dataset to try to isolate the problem.
Hello,
I have problem retrieving individual element of xml through ArrayCollection. The details as below:
XML gallery.xml looks like this-
image 1
title for Image 1
.
.
.
.
am converting the XMl to array collection as below:
Step1: Calling the resulthandler..code as below-
Step2: Converting xml to Array Collection
[Bindable]
public var galleryData:ArrayCollection;
protected function resultHandler(event:ResultEvent):void
{
galleryData=event.result.gallery.images;
//want to use individual value of galleryData here
}
Now somewhere in the code I am setting text for image using label:
My query is-in the result handler I want to set the image text by geeting each value of text value of image from galleryData which now holds xml.
Please help!
Donno why above message didin’t include code for label, well here it is
s:Label x=”31″ y=”603″ text=”This is infor for picture4″ width=”312″ height=”39″ color=”#E1E4EB” id=”label4″
Thank you Hillel, you saved a lot of time with your method. I hope that i can contact you later for other questions concerning flex!
Med,
Happy it saved you time. Although I try to support any components/posts on my blog I don’t usually provide general Flex support (if I did I’m sure I’d be spending quite a bit of my time doing it). I’d recommend posting to the Flex forums if you have any questions.
Best,
Hillel
Do you have any ideas how to get the SimpleXMLDecoder values just in string format. Now if I give string 89.3450 it gives me 89.345 because it thinks the value is a number.
Thanks!
Tuomas
Tuomas,
I’m not sure how to accomplish that with the SimpleXMLDecoder. You may want to take a look at the spicelib XML to Object mapper
http://www.spicefactory.org/parsley/docs/2.2/manual/xmlmapper.php#intro
Hope this helps,
Hillel
Какие положительные результаты 🙂
Thanks.
It helped a lot.
Hi,
Can you tell what’s the problem when the array at the end of the funtion retuns [object Object]?
Thanks
Doris
Doris,
I’m not sure I’m following, could you please try clarifying your question.
Thanks
Sure!
I think the problem comes from my xml transformation to string, but:
Below you’ll find the code I utilized.
The function returns: array = [object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Do you know why? where I am wrong?
private function convertXmlToArrayCollection(file:String):ArrayCollection {
var xmlStr:String = file;
var xmlDoc:XMLDocument = new XMLDocument(xmlStr);
var decoder:SimpleXMLDecoder = new SimpleXMLDecoder();
var resultObject:Object = decoder.decodeXML(xmlDoc);
var array:Array = ArrayUtil.toArray(resultObject.items.item);
return new ArrayCollection(array);
}
Doris,
I’d suggest using ObjectUtil.toString() to get a better look at the result from the function.
thank you very much
you save my time
Hi its very good post.Thanks a lot.
Sorry for the ugliness of the post, but under code or without code tag i can’t present xml.
This question is the form of genealogy. Where every node has the capability to expand exponentially. All nodes can have children that divide and have children of there own. How to either parse xml like this or convert it to an array collection. The simple xml of 1 child with 1 attribute is easy to do, but how do you do xml that can have different subjects who have their own children?
If this displays right… I used ( because < these failed.
(parent)
(child 1)
(name)george(/name)
(grandchild)
(name)frank(/name)
(greatgrandchild)
(name)Elmo(/name)
(/greatgrandchild)
(greatgrandchild)
(name)Big Bird(/name)
(/greatgrandchild)
(/grandchild)
(/child)
(parents)
(mother)
(name)susie(/name)
(dob)1824(/dob)
(/mother)
(/parents)
(/parent)
The idea is how to parse elements when you not sure how many or what they might be with multiple child nodes and they all have children of themself.
mingster,
I’m sorry, I haven’t yet been able to find a solution to this.
thanks brother ur code saved a lot time for me. i am expecting more codes like this form you.
thanks, your approach was the solution!
Thanks again Hillel..You saved me again…use this one after AutoComplete component…
God Bless ya..
realy thnx..
Vinit,
Brilliant, happy to hear it
Best,
Hillel
you, sir, are a life saver!
Hi Hilel
i got this error
1046: Type was not found or was not a compile-time constant: XMLDocument.
1180: Call to a possibly undefined method convertXmlToArrayCollection.
how to fix this?
thanks
Hilel,
nevermind about my previous question, just removed and use autocomplete from flex then everything just ok 😀
thanks
thank you for blog (even today it works)
nice, happy to hear it
Been using simpleXMLDecoder successfully for some time but have now come across a problem when using data returned from Facebook.
Data return looks like :-
2156783514916597080
2156783514925485319
10150247237985295
4
Wall Photos
2156783514916480723
2156783514925409064
10150240208950295
18
Profile Pictures
…..
I use the follwing to ‘decode it’
var array:Array =new Array();
var xeml:XMLDocument = new XMLDocument(file);
var decoder:SimpleXMLDecoder = new SimpleXMLDecoder();
var data:Object = decoder.decodeXML(xeml);
if(data.hasOwnProperty(“fql_query_response”))
{
if(data.fql_query_response.hasOwnProperty(“album”))
{
array = ArrayUtil.toArray(data.fql_query_response.album);
}
else
{
array= ArrayUtil.toArray(data.fql_query_response.photo);
}
}
return new ArrayCollection(array);
Only problem is the ‘aid’ value that is ‘decoded out’ is different from what was in the returned
The aid decoded out is 2156783514916596992
that what was in the returned file for this object was 2156783514916597080
Any idea why ?
It’s possible it’s handling it as a number (rather than a string) and running into a precision problem.
Thanks! This saved a lot of time – the hardest thing for me in Flex is constantly converting XML to the various data types I need.
Great, happy to hear it helped.
Best,
Hillel
Hi. This has also helped me a lot. But I have one problem which is that if I have no data for one of the cells, datagrid is filled with [object Object]. I’ve tried reading the arraycollection and asigning value to ” “, but as value in fact doesnt exist, it doesnt work. The structure of the xml is something like
value
This is converted to arraycollection as:
arr[0][field1].type = x
arr[0][field1].value = value
arr[0][field2].type = x
arr[0][field2].value———->it doesnt exists so that cell in the dataprovider of the datagrid appears like [object Object]
Any ideas?
You may be able to solve this using a label function or custom renderer in the datagrid.
Thats right. I’ve eventually used labelfunction. Thanks
Thank you for this. I wanted to make my helper method more customizable for different XML files, so this is my implementation:
/**
* Converts XML object to ArrayCollection. Use the callback to drill into the XML model to get to your collection.
* @param xml XML object to convert
* @param callback Optional callback function to drill into the XML model
*
function callback(data:Object):Object
* @return The converted ArrayCollection
**/
public static function convertXmlToArrayCollection(xml:XML, callback:Function = null):ArrayCollection
{
// convert XML to XMLDocument
var xmlStr:String = xml.toString();
var xmlDoc:XMLDocument = new XMLDocument(xmlStr);
// convert XMLDocument to Object
var decoder:SimpleXMLDecoder = new SimpleXMLDecoder();
var data:Object = decoder.decodeXML(xmlDoc);
// drill down data using callback if provided
if (callback != null)
{
data = callback(data);
}
// convert Object to ArrayCollection
var array:Array = ArrayUtil.toArray(data);
return new ArrayCollection(array);
}
Usage:
var coll:ArrayCollection = convertXmlToArrayCollection(xml, function(xmlObject:Object):Object { return xmlObject.list.item; });
That’s a great solution! Thanks for submitting it.
Merci beaucoup very nice post.
Thanks for the solution, it works perfectly!!!!