Welcome, Guest. Please login or register.
Did you miss your activation email?
31 Jul 2010, 11:37:50 UTC
Forum home
+  flexdeveloper.eu Forum
|-+  Flex and ActionScript 3.0
| |-+  Flex 3 Framework (Moderators: JMWhittaker, Jan K, thewarpedcoder, James)
| | |-+  complex XML and datagrids
« previous next »
Pages: [1] Print
Author Topic: complex XML and datagrids (Read 9099 times)
Elsa
Guest
« on: 06 Aug 2006, 00:38:38 UTC »

Why is it that in all the examples around XML and Flex that the XML is really simple and doesn't reflect a real world situation
e.g.
Code:
<items>
   <item>
    <code>34214</code>
    <desc>foo</desc>
    <price>23</price>
   </item>
   <item>
    <code>42234</code>
    <desc>bar</desc>
    <price>56</price>
   </item>
  </items>

that's all well and good but what happens if your data isn't that simple?
e.g.
Code:
<items>
   <item>
    <code>34214</code>
    <child>
      <moredata>
         Here is the data I want
       </moredata>
    </child>
    <desc>foo</desc>
    <price>23</price>
   </item>
   <item>
    <code>42234</code>
    <child>
      <moredata>
         Here is the data I want
      </moredata>
    </child>
    <desc>bar</desc>
    <price>56</price>
   </item>
  </items>

If I hold that data in an XML object I can burrow down using the . syntax, but more commonly examples hold the data in an ArrayCollection. However when I use an ArrayCollection, if I try and return the data in a DataGrid I get [objectObect] for the child field moredata.

Is there a way to bury further into the data to retrieve results or do I need to handle the data differently when I creat the array, such as a custom data descriptor?

Perhaps I need to use an XMLListCollection? But if so - why are most examples using an ArrayCollection.
 Cry
« Last Edit: 06 Aug 2006, 15:29:24 UTC by Elsa » Logged
Elsa
Guest
« Reply #1 on: 06 Aug 2006, 01:18:20 UTC »

Starter for 10...
http://thanksmister.com/?p=8

Ok tried using his example with ArrayCollection and it works:
Code:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"  width="450" height="186"
      creationComplete="onCreationComplete();">
    <mx:Script>
     <![CDATA[
         import mx.collections.ArrayCollection;
         import mx.controls.Alert;
         import mx.rpc.events.ResultEvent;
        
        [Bindable]
        private var xmlData:ArrayCollection;
      
        
        private function onCreationComplete():void
            {
                   // Load the XML file
                   latest.send();      
             }
        
        private function onResult( event:ResultEvent ):void
        {
                  xmlData = event.result.people.person;
            }  

            private function myLabelFunc(item:Object, column:DataGridColumn):String
        {
             if (item.address.number==undefined)
                  {return null;}
             else
                  {return item.address.number + " " + item.address.street;}
        }
     ]]>
    </mx:Script>
          <mx:HTTPService id="latest" url="data/xmldata.xml"
            result="onResult(event);"
             />
    
 <!--<mx:ArrayCollection id="xmlData"/> -->
    
    <mx:DataGrid id="myDataGrid2" dataProvider="{xmlData}" right="10" bottom="10" left="10" top="40">
          <mx:columns>
            <mx:DataGridColumn dataField="name" headerText="Name"/>
            <mx:DataGridColumn dataField="age" headerText="Age"/>
            <mx:DataGridColumn headerText="Address"  labelFunction="myLabelFunc"/>
         </mx:columns>
    </mx:DataGrid>
    <mx:Label x="10" y="10" text="Binding Complex XML to DataGrid" fontWeight="bold"/>
</mx:Application>

So it must be to do with the fact that my array collection is built in one component and the datagrid is in a child component. I'm currently passing the array via a get and set method. Will keep trying as there must be a way.
« Last Edit: 06 Aug 2006, 16:21:05 UTC by Elsa » Logged
Elsa
Guest
« Reply #2 on: 06 Aug 2006, 15:28:48 UTC »

More info on complex XML and datagrids...
http://weblogs.macromedia.com/eanderson/archives/2004/12/using_complex_x.cfm
Logged
Elsa
Guest
« Reply #3 on: 06 Aug 2006, 19:50:09 UTC »

Got it working!  Grin

My problem was a rather embarrasing coding error  Embarrassed Lips sealed
Logged
Elsa
Guest
« Reply #4 on: 06 Aug 2006, 22:15:35 UTC »

Ok the above method is working great if there is only one result to be returned. But I have several instances where there are a more than one result for a single property, e.g more than one film genre,  so I presume I need to loop through these somehow.
Currently I'm getting an "Unknown Property" error if I try to get to the data I need.

If I am tring to return all the genre.displayname data....

It will return a reult for:
Code:
<genres>
      <genre>
            <displayname>Comedy</displayname>
            <sortname>Comedy</sortname>
      </genre>
</genres>

But not for:
Code:
                 <genres>
                        <genre>
                              <displayname>Comedy</displayname>
                              <sortname>Comedy</sortname>
                        </genre>
                        <genre>
                              <displayname>Drama</displayname>
                              <sortname>Drama</sortname>
                        </genre>
                        <genre>
                              <displayname>Romance</displayname>
                              <sortname>Romance</sortname>
                        </genre>
                  </genres>
« Last Edit: 07 Aug 2006, 19:13:14 UTC by Elsa » Logged
Elsa
Guest
« Reply #5 on: 07 Aug 2006, 23:46:52 UTC »

It took me a while but I finally got a for loop working to pull out the data I needed:

Not sure if I could do it a better way, but frankly I'm just delighted to have it working at the moment  Grin
Code:
              private function genreFunction(data:Object, column:DataGridColumn):String
                  {
                        var myGenres:String;
                        myGenres = "";
                  
                        for each(data.genres.genre in data.genres)
                        {
                              if (data.genres.genre[0]==null)
                              {
                                    myGenres = data.genres.genre.displayname;
                              }
                              else
                              {

                                    for (var genre:String in data.genres.genre)
                                    {
                                    myGenres += data.genres.genre[genre].displayname + ", ";
                                    }
                              }
                        }
                        return myGenres;                  
                        
                  }  

The key was in getting to grips with the differnence between for...in and for each...in loops:

Quote
for..in

The for..in loop iterates through the properties of an object, or the elements of an array. For example, you can use a for..in loop to iterate through the properties of a generic object (object properties are not kept in any particular order, so properties may appear in a seemingly random order):

Code:
var myObj:Object = {x:20, y:30};
for (var i:String in myObj) {
    trace (i + ": " + myObj[i]);
}
// output:
// x: 20
// y: 30

You can also iterate through the elements of an array:

Code:
var myArray:Array = ["one", "two", "three"];
for (var i:String in myArray) {
    trace (myArray[i]);
}
// output:
// one
// two
// three

What you cannot do is iterate through the properties of an object if it is an instance of a user-defined class, unless the class is a dynamic class. Even with instances of dynamic classes, you will be able to iterate only through properties that are added dynamically.

for each..in

The for each..in loop iterates through the items of a collection, which can be tags in an XML or XMLList object, the values held by object properties, or the elements of an array. For example, as the following excerpt shows, you can use a for each..in loop to iterate through the properties of a generic object, but unlike the for..in loop, the iterator variable in a for each..in loop contains the value held by the property instead of the name of the property:

Code:
var myObj:Object = {x:20, y:30};
for each (var num in myObj) {
    trace (num);
}
// output:
// 20
// 30

You can iterate through an XML or XMLList object, as the following example shows:
Code:
var myXML:XML = <users>
                   <fname>Jane</fname>
                   <fname>Susan</fname>
                   <fname>John</fname>
                </users>;

for each (var item in myXML.fname) {
    trace(item);
}
/* output
Jane
Susan
John
*/

You can also iterate through the elements of an array, as this example shows:

Code:
var myArray:Array = ["one", "two", "three"];
for each (var item in myArray) {
    trace (item);
}
// output:
// one
// two
// three

You cannot iterate through the properties of an object if the object is an instance of a sealed class. Even for instances of dynamic classes, you cannot iterate through any fixed properties, which are properties defined as part of the class definition.
from Adobe docs
« Last Edit: 07 Aug 2006, 23:52:07 UTC by Elsa » Logged
Pages: [1] Print
« previous next »
Share this on: Twitter Twitter Del.icio.us del.icio.us Digg Digg
Jump to:

©2006-2010 Flexdeveloper.eu/Jodie O'Rourke. All rights reserved.
Adobe®, Adobe® Flash™, Adobe® AIR™ and Adobe® Flex™ are registered trademarks of Adobe Systems Incorporated in the United States and other countries. All rights reserved.

Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC