Solved

Flex Tree from Complex XML

Posted on 2009-05-13
6
4,476 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
ID: 24374086
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
ID: 24382573
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
ID: 24383827
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
VMware Disaster Recovery and Data Protection

In this expert guide, you’ll learn about the components of a Modern Data Center. You will use cases for the value-added capabilities of Veeam®, including combining backup and replication for VMware disaster recovery and using replication for data center migration.

 

Author Comment

by:enjay99
ID: 24392597
Fantastic !!!

Thank you mplord.
0
 

Author Comment

by:enjay99
ID: 24392617
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
ID: 24393668
Hi - no problem :)
0

Featured Post

Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Adobe AIR in bar  launch 3 278
Flex automation testing 8 698
flex - list item renderer 7 679
Can't get dispatchEvent to work when parent to talk to child AS3 3 568
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…
This article outlines why you need to choose a backup solution that protects your entire environment – including your VMware ESXi and Microsoft Hyper-V virtualization hosts – not just your virtual machines.
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

803 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