Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 4491
  • Last Modified:

Flex Tree from Complex XML

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
enjay99
Asked:
enjay99
  • 3
  • 3
1 Solution
 
mplordCommented:
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
 
enjay99Author Commented:
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
 
mplordCommented:
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
Improve Your Query Performance Tuning

In this FREE six-day email course, you'll learn from Janis Griffin, Database Performance Evangelist. She'll teach 12 steps that you can use to optimize your queries as much as possible and see measurable results in your work. Get started today!

 
enjay99Author Commented:
Fantastic !!!

Thank you mplord.
0
 
enjay99Author Commented:
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
 
mplordCommented:
Hi - no problem :)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

What Kind of Coding Program is Right for You?

There are many ways to learn to code these days. From coding bootcamps like Flatiron School to online courses to totally free beginner resources. The best way to learn to code depends on many factors, but the most important one is you. See what course is best for you.

  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now