Solved

Flex Tree from Complex XML

Posted on 2009-05-13
6
4,471 Views
Last Modified: 2012-05-06
Hi Genius'

I have been struggling with this for about a week now so it is time to ask for some help.
I have a well formed XML file that I receive from a server (please see original.xml) and I would like to represent it as a tree that the user can click on a leaf and be able to edit the elements associated with that item in fields to the right of the tree (either a dataGrid or a series of textInput fields.)

My problem is how to get it into a tree and tightly bound to the XML.

All of the examples that I have found mysteriously change from xml with elements in it into XML with only attributes (something like tree_1.xml). This is not useful as the actual data I am using has many elements attached to each leaf and sometimes multiple attributes.

My gut feeling (with very little experience in these matters) is to reformat the original.xml into a tree structure (like tree_2.xml), bind it to an XMLListCollection and create a tree by using a labelFunction.

I have two problems with this approach:

    1. XMLListCollection does not seem to like the tree structure XML
    2. If I write a labelFunction like:

private function getTreeLabel(item:Object):String
            {
                var node:XML = XML(item);
                if( node.localName() == "Desc" )
                    return node;
               else
                   return null;
            }

I can do this by using the HTTPService as the dataProvider I get the branches and leaves I want but I also get a blank tree item for each of the nulls

I hope I have described the problem clearly as it is now very late here.
Going around in circles and very tired, so any help would be much appreciated.

Best Regards,






original.xml
 

<treeID>103</treeID>

<treeType>Oak</treeType>

<branches>

    <branch>

        <id label="branch ID" dbid="0">290</id>

        <branchCode label="branch Code" dbid="1">A</branchCode>

        <branchTitle label="Title" dbid="2">Small Branch</branchTitle>

    </branch>

    <branch>

        <id label="branch ID" dbid="0">391</id>

        <branchCode label="branch Code" dbid="1">B</branchCode>

        <branchTitle label="Title" dbid="2">Big Branch</branchTitle>

    </branch>

</branches>
 

<leaves>

    <leaf>

        <id label="leaf ID" dbid="0">48</id>

        <leafCode label="leaf Code" dbid="1">xBBLeaf1</leafCode>

        <leafDesc label="leaf Description" dbid="3">Big Branch Leaf One</leafDesc>

        <onbranchs label="Appear on branchs" dbid="5">B</onbranchs>

        <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

        <leafSize label="Leaf Size" dbid="10">123</leafSize>

    </leaf>

    <leaf>

        <id label="leaf ID" dbid="0">138</id>

        <leafCode label="leaf Code" dbid="1">yBBLeaf2</leafCode>

        <leafDesc label="leaf Description" dbid="3">Big Branch Leaf Two</leafDesc>

        <onbranchs label="Appear on branchs" dbid="5">B</onbranchs>

        <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

        <leafSize label="Leaf Size" dbid="10">124</leafSize>

    </leaf>

    <leaf>

        <id label="leaf ID" dbid="0">49</id>

        <leafCode label="leaf Code" dbid="1">Unileaf</leafCode>

        <leafDesc label="leaf Description" dbid="3">The Multi Leaf</leafDesc>

        <onbranchs label="Appear on branchs" dbid="5">AB</onbranchs>

        <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

        <leafSize label="Leaf Size" dbid="10">125</leafSize>

    </leaf>

    <leaf>

        <id label="leaf ID" dbid="0">44</id>

        <leafCode label="leaf Code" dbid="1">SBLeaf1</leafCode>

        <leafDesc label="leaf Description" dbid="3">Small Branch Leaf One</leafDesc>

        <onbranchs label="Appear on branchs" dbid="5">A</onbranchs>

        <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

        <leafSize label="Leaf Size" dbid="10">126</leafSize>

    </leaf>

    <leaf>

        <id label="leaf ID" dbid="0">42</id>

        <leafCode label="leaf Code" dbid="1">SBLeaf2</leafCode>

        <leafDesc label="leaf Description" dbid="3">Small Branch Leaf Two</leafDesc>

        <onbranchs label="Appear on branchs" dbid="5">A</onbranchs>

        <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

        <leafSize label="Leaf Size" dbid="10">127</leafSize>

    </leaf>

</leaves>
 

=================================================================
 

tree_1.xml
 

<tree>

<branches>

    <branch id="290" branchCode="A" label="Small Branch" />

        <leaves>

            <branch id="44" leafCode="xSBLeaf1" label="Small Branch Leaf One" />

            <branch id="42" leafCode="xSBLeaf1" label="Small Branch Leaf Two" />

            <branch id="49" leafCode="Uni" label="The Multi Leaf" />

        </leaves>

    </branch>

    <branch id="391" branchCode="B" label="Big Branch" />

        <leaves>

            <branch id="48" leafCode="xBBLeaf1" label="Big Branch Leaf One" />

            <branch id="138" leafCode="xBBLeaf1" label="Big Branch Leaf Two" />

            <branch id="49" leafCode="Uni" label="The Multi Leaf" />

        </leaves>

    </branch>

</branches>

</tree>
 

====================================================================
 
 

<tree>

<branches>

    <branch id label="branch ID" dbid="0">290</id>

        <branchCode label="branch Code" dbid="1">A</branchCode>

        <Desc label="Title" dbid="2">Small Branch</branchTitle>

        <leaves>

            <leaf>

                <id label="leaf ID" dbid="0">49</id>

                <leafCode label="leaf Code" dbid="1">Unileaf</leafCode>

                <Desc label="leaf Description" dbid="3">The Multi Leaf</leafDesc>

                <onbranchs label="Appear on branchs" dbid="5">AB</onbranchs>

                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

                <leafSize label="Leaf Size" dbid="10">125</leafSize>

            </leaf>

            <leaf>

                <id label="leaf ID" dbid="0">44</id>

                <leafCode label="leaf Code" dbid="1">SBLeaf1</leafCode>

                <Desc label="leaf Description" dbid="3">Small Branch Leaf One</leafDesc>

                <onbranchs label="Appear on branchs" dbid="5">A</onbranchs>

                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

                <leafSize label="Leaf Size" dbid="10">126</leafSize>

            </leaf>

            <leaf>

                <id label="leaf ID" dbid="0">42</id>

                <leafCode label="leaf Code" dbid="1">SBLeaf2</leafCode>

                <Desc label="leaf Description" dbid="3">Small Branch Leaf Two</leafDesc>

                <onbranchs label="Appear on branchs" dbid="5">A</onbranchs>

                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

                <leafSize label="Leaf Size" dbid="10">127</leafSize>

            </leaf>

        </leaves>

    </branch>

    <branch>

        <id label="branch ID" dbid="0">391</id>

        <branchCode label="branch Code" dbid="1">B</branchCode>

        <Desc label="Title" dbid="2">Big Branch</branchTitle>

        <leaves>

            <leaf>

                <id label="leaf ID" dbid="0">48</id>

                <leafCode label="leaf Code" dbid="1">xBBLeaf1</leafCode>

                <Desc label="leaf Description" dbid="3">Big Branch Leaf One</leafDesc>

                <onbranchs label="Appear on branchs" dbid="5">B</onbranchs>

                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

                <leafSize label="Leaf Size" dbid="10">123</leafSize>

            </leaf>

            <leaf>

                <id label="leaf ID" dbid="0">138</id>

                <leafCode label="leaf Code" dbid="1">yBBLeaf2</leafCode>

                <Desc label="leaf Description" dbid="3">Big Branch Leaf Two</leafDesc>

                <onbranchs label="Appear on branchs" dbid="5">B</onbranchs>

                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

                <leafSize label="Leaf Size" dbid="10">124</leafSize>

            </leaf>

            <leaf>

                <id label="leaf ID" dbid="0">49</id>

                <leafCode label="leaf Code" dbid="1">Unileaf</leafCode>

                <Desc label="leaf Description" dbid="3">The Multi Leaf</leafDesc>

                <onbranchs label="Appear on branchs" dbid="5">AB</onbranchs>

                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

                <leafSize label="Leaf Size" dbid="10">125</leafSize>

            </leaf>

        </leaves>        

    </branch>

</branches>

</tree>

Open in new window

0
Comment
Question by:enjay99
  • 3
  • 3
6 Comments
 
LVL 10

Expert Comment

by:mplord
Comment Utility
You are right, the tree XML you provide to the Tree control will need to be formatted in a way that the Tree control will accept. So you'll have to transform the XML you get from the HTTPService request before you can use it exactly as you need in the tree, then once edited transform it back to the format you require before sending it back for update etc.

Your tree_2.xml had to be modified slightly as your tags were not matching correctly (probably your tiredness right ;) - the following example should help you see how to show the complete (bound) tree including element values.

Remember though that elements are still children of the enclosing tags, so will always appear as child nodes in the tree. If for example you want to show the id element value as the label for the id node, you'll have to reformat your XML to provide the id value as an attribute of the id node then update the getTreeLabel function to build the label string.


<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init();">
 

	<mx:Script>

		<![CDATA[

			[Bindable] private var model:XML = 

				<tree>

					<branches>

					    <branch>

					    	<id label="branch ID" dbid="0">290</id>

					        <branchCode label="branch Code" dbid="1">A</branchCode>

					        <branchTitle label="Title" dbid="2">Small Branch</branchTitle>

					        <leaves>

					            <leaf>

					                <id label="leaf ID" dbid="0">49</id>

					                <leafCode label="leaf Code" dbid="1">Unileaf</leafCode>

					                <leafDesc label="leaf Description" dbid="3">The Multi Leaf</leafDesc>

					                <onbranchs label="Appear on branchs" dbid="5">AB</onbranchs>

					                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

					                <leafSize label="Leaf Size" dbid="10">125</leafSize>

					            </leaf>

					            <leaf>

					                <id label="leaf ID" dbid="0">44</id>

					                <leafCode label="leaf Code" dbid="1">SBLeaf1</leafCode>

					                <leafDesc label="leaf Description" dbid="3">Small Branch Leaf One</leafDesc>

					                <onbranchs label="Appear on branchs" dbid="5">A</onbranchs>

					                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

					                <leafSize label="Leaf Size" dbid="10">126</leafSize>

					            </leaf>

					            <leaf>

					                <id label="leaf ID" dbid="0">42</id>

					                <leafCode label="leaf Code" dbid="1">SBLeaf2</leafCode>

					                <leafDesc label="leaf Description" dbid="3">Small Branch Leaf Two</leafDesc>

					                <onbranchs label="Appear on branchs" dbid="5">A</onbranchs>

					                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

					                <leafSize label="Leaf Size" dbid="10">127</leafSize>

					            </leaf>

					        </leaves>

					    </branch>

					    <branch>

					        <id label="branch ID" dbid="0">391</id>

					        <branchCode label="branch Code" dbid="1">B</branchCode>

					        <branchTitle label="Title" dbid="2">Big Branch</branchTitle>

					        <leaves>

					            <leaf>

					                <id label="leaf ID" dbid="0">48</id>

					                <leafCode label="leaf Code" dbid="1">xBBLeaf1</leafCode>

					                <leafDesc label="leaf Description" dbid="3">Big Branch Leaf One</leafDesc>

					                <onbranchs label="Appear on branchs" dbid="5">B</onbranchs>

					                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

					                <leafSize label="Leaf Size" dbid="10">123</leafSize>

					            </leaf>

					            <leaf>

					                <id label="leaf ID" dbid="0">138</id>

					                <leafCode label="leaf Code" dbid="1">yBBLeaf2</leafCode>

					                <leafDesc label="leaf Description" dbid="3">Big Branch Leaf Two</leafDesc>

					                <onbranchs label="Appear on branchs" dbid="5">B</onbranchs>

					                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

					                <leafSize label="Leaf Size" dbid="10">124</leafSize>

					            </leaf>

					            <leaf>

					                <id label="leaf ID" dbid="0">49</id>

					                <leafCode label="leaf Code" dbid="1">Unileaf</leafCode>

					                <leafDesc label="leaf Description" dbid="3">The Multi Leaf</leafDesc>

					                <onbranchs label="Appear on branchs" dbid="5">AB</onbranchs>

					                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

					                <leafSize label="Leaf Size" dbid="10">125</leafSize>

					            </leaf>

					        </leaves>        

					    </branch>

					</branches>

				</tree>

				

				private function init():void

				{

					tree.dataProvider = model;

				}	

				

				private function getTreeLabel(item:Object):String

				{

					var node:XML = XML(item);

					if( node.localName() == null )

						return node.toString();

					else

					{

						switch (node.localName())

						{

							//eg

							case "leafDesc":

								return "leafDesc: " + node.@label;

								break;

						}						

					}

					// default

					return node.localName();

				}

		]]>

	</mx:Script>
 

	<mx:Tree id="tree" horizontalCenter="0" verticalCenter="7" width="472" height="380" labelFunction="getTreeLabel"></mx:Tree>

	

</mx:Application>

Open in new window

0
 

Author Comment

by:enjay99
Comment Utility
Dear mplord,

Thank you for your excellent response, what a great service.

As you mentioned though all the elements are still children of the enclosing tags, so will always appear as child nodes in the tree.

I was hoping to use the getTreeLabel function to only list the Title of the branch or leaf, but bind to the rest of the data elements of the leaf for editing in another part of the screen.

Perhaps that is asking a bit too much of the flex tree and will have to create a tree of only the Titles and somehow "point" to the data for editing.
0
 
LVL 10

Accepted Solution

by:
mplord earned 500 total points
Comment Utility
You can use a custom data descriptor for the tree to help with this.

I've created a new class CustomDescriptor which overrides DefaultDataDescriptor, and is provided to the tree as it's dataDescriptor.

You'll have to add an event to detect when you've selected a node in the tree, and bind your editing fields to the node depending on it's type etc.

Hope this helps.

###### MAIN APPLICATION
 

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init();" xmlns:my="*">
 

	<mx:Script>

		<![CDATA[

			[Bindable] private var model:XML = 

				<tree>

					<branches>

					    <branch>

					    	<id label="branch ID" dbid="0">290</id>

					        <branchCode label="branch Code" dbid="1">A</branchCode>

					        <branchTitle label="Title" dbid="2">Small Branch</branchTitle>

					        <leaves>

					            <leaf>

					                <id label="leaf ID" dbid="0">49</id>

					                <leafCode label="leaf Code" dbid="1">Unileaf</leafCode>

					                <leafDesc label="leaf Description" dbid="3">The Multi Leaf</leafDesc>

					                <onbranchs label="Appear on branchs" dbid="5">AB</onbranchs>

					                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

					                <leafSize label="Leaf Size" dbid="10">125</leafSize>

					            </leaf>

					            <leaf>

					                <id label="leaf ID" dbid="0">44</id>

					                <leafCode label="leaf Code" dbid="1">SBLeaf1</leafCode>

					                <leafDesc label="leaf Description" dbid="3">Small Branch Leaf One</leafDesc>

					                <onbranchs label="Appear on branchs" dbid="5">A</onbranchs>

					                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

					                <leafSize label="Leaf Size" dbid="10">126</leafSize>

					            </leaf>

					            <leaf>

					                <id label="leaf ID" dbid="0">42</id>

					                <leafCode label="leaf Code" dbid="1">SBLeaf2</leafCode>

					                <leafDesc label="leaf Description" dbid="3">Small Branch Leaf Two</leafDesc>

					                <onbranchs label="Appear on branchs" dbid="5">A</onbranchs>

					                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

					                <leafSize label="Leaf Size" dbid="10">127</leafSize>

					            </leaf>

					        </leaves>

					    </branch>

					    <branch>

					        <id label="branch ID" dbid="0">391</id>

					        <branchCode label="branch Code" dbid="1">B</branchCode>

					        <branchTitle label="Title" dbid="2">Big Branch</branchTitle>

					        <leaves>

					            <leaf>

					                <id label="leaf ID" dbid="0">48</id>

					                <leafCode label="leaf Code" dbid="1">xBBLeaf1</leafCode>

					                <leafDesc label="leaf Description" dbid="3">Big Branch Leaf One</leafDesc>

					                <onbranchs label="Appear on branchs" dbid="5">B</onbranchs>

					                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

					                <leafSize label="Leaf Size" dbid="10">123</leafSize>

					            </leaf>

					            <leaf>

					                <id label="leaf ID" dbid="0">138</id>

					                <leafCode label="leaf Code" dbid="1">yBBLeaf2</leafCode>

					                <leafDesc label="leaf Description" dbid="3">Big Branch Leaf Two</leafDesc>

					                <onbranchs label="Appear on branchs" dbid="5">B</onbranchs>

					                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

					                <leafSize label="Leaf Size" dbid="10">124</leafSize>

					            </leaf>

					            <leaf>

					                <id label="leaf ID" dbid="0">49</id>

					                <leafCode label="leaf Code" dbid="1">Unileaf</leafCode>

					                <leafDesc label="leaf Description" dbid="3">The Multi Leaf</leafDesc>

					                <onbranchs label="Appear on branchs" dbid="5">AB</onbranchs>

					                <leafDate label="Leaf Date" dbid="7">12-04-09</leafDate>

					                <leafSize label="Leaf Size" dbid="10">125</leafSize>

					            </leaf>

					        </leaves>        

					    </branch>

					</branches>

				</tree>

				

				private function init():void

				{

					tree.dataProvider = model;

				}	

				

				private function getTreeLabel(item:Object):String

				{

					var node:XML = XML(item);

					if( node.localName() == null )

						return node.toString();

					else

					{

						switch (node.localName())

						{

							//eg

							case "leaf":

								return "leaf: " + node.leafDesc.children()[0].toString();

								break;

							case "branch":

								return "branch: " + node.branchTitle.children()[0].toString();

								break;

						}						

					}

					// default

					return node.localName();

				}

		]]>

	</mx:Script>
 

	<mx:Tree dataDescriptor="{new CustomDescriptor()}" id="tree" horizontalCenter="0" verticalCenter="7" width="472" height="380" labelFunction="getTreeLabel"></mx:Tree>

	

</mx:Application>
 
 

###### CustomDescriptor.as
 

package

{

	import mx.collections.ICollectionView;

	import mx.collections.XMLListCollection;

	import mx.controls.treeClasses.DefaultDataDescriptor;

	

	public class CustomDescriptor extends DefaultDataDescriptor

	{

		public function CustomDescriptor()

		{

		}
 

		override public function hasChildren(node:Object, model:Object = null):Boolean

		{

			if (node is XML)

			{

				var xmlnode:XML = node as XML;

				switch (xmlnode.localName())

				{

					case "leaf":

						return false;

					case "branch":

						return ((xmlnode.leaves as XMLList).length() > 0);

				}

			}

			return super.hasChildren(node, model);

		}
 

		override public function isBranch(node:Object, model:Object = null):Boolean

		{

			if (node is XML)

			{

				var xmlnode:XML = node as XML;

				if (xmlnode.localName() == "leaf") return false;

			}

			return super.hasChildren(node, model);

		}
 

		override public function getChildren(node:Object, model:Object = null):ICollectionView

		{

			if (node is XML)

			{

				var xmlnode:XML = node as XML;

				switch (xmlnode.localName())

				{

					case "branch":

						return new XMLListCollection(xmlnode.leaves.leaf as XMLList);

				}

			}

			return super.getChildren(node, model);

		}
 

	}

}

Open in new window

0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:enjay99
Comment Utility
Fantastic !!!

Thank you mplord.
0
 

Author Comment

by:enjay99
Comment Utility
Sorry mplord,

Could you please ping one more note, so that I can award points.
I said thank you in a comment without realizing how things work.
0
 
LVL 10

Expert Comment

by:mplord
Comment Utility
Hi - no problem :)
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Flex Builder 4.5 3 394
Deleting Objects in flex 1 357
Port 4000 issue 1 1,886
Issue running Flash Builder application in Google Chrome 2 919
First things first - Preparation We need all the part for this install and it's much nicer to have them all on hand when you need them so here's what's required. Download Eclipse 3.5 32 bit (I like the Classic flavour) from here. (http://www.e…
Restoring deleted objects in Active Directory has been a standard feature in Active Directory for many years, yet some admins may not know what is available.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now