• Coding
  • [Actionscript] Checking if an XML node has children

Hey guys. I'm trying to build a multi-level XML drop down menu. The point is to retrieve all the data from an XML file, parse it in AS3.0 and do the magic. Some of my XML nodes have child nodes but others don't. The parent nodes will be top level menu items, while the child nodes will be the sub level menu items i.e these will drop down. My plan is to load the top level parent nodes (which is working fine so far) and then check whether this node has children, and if it does then I want to load those nodes and construct the drop down menu. But I'm having trouble to get past the top level parent nodes... anyway, here's my XML and AS3 code so far:
<menu>
	<item text="Home" link="www.google.com">
	</item>
	
	<item text="About">
		<sub text="About Us" link="www.facebook.com"></sub>
		<sub text="Biography" link="www.google.com"></sub>
	</item>
	
	<item text="Portfolio">
		<sub text="Flash" link="www.developphp.com"></sub>
		<sub text="PHP/MySQL" link="www.php.net"></sub>
		<sub text="Print Design" link="www.cssmania.com"></sub>
		<sub text="Community" link="www.lebgeeks.com"></sub>
	</item>
	
	<item text="Contact Us" link="www.facebook.com">
	</item>
</menu>
and here's part of my AS3 code
               private function xmlLoaded(e:Event):void
		{
			xmlLoader.removeEventListener(Event.COMPLETE, xmlLoaded);
			xmlData = new XML(e.target.data);
			menuList = new XMLList(xmlData.item);
			parseXML();
		}
		
		private function parseXML():void
		{
			menuItems = new Array();
			for (var i:uint = 0; i < menuList.length(); i++)
			{
				var item:MenuItem = new MenuItem();
				item.x = (item.width + offset) * i;
				item.y = 10;
				item.textBox.text = menuList[i].@text;
				item.textBox.mouseEnabled = false;
				item.link = menuList[i].@link;
				item.buttonMode = true;
				menuItems.push(item);
				addChild(item);
				checkForChildren(menuList[i]);
			}
		}
		
		private function checkForChildren(node:XML):void
		{
			trace(node.children.length()); //outputs 0's
		}
EDIT: found some problems in the code so I edited them but I'm still stuck...
ok according to THIS LINK it seems like my best chance of doing that is by using the hasChildNodes() method. But it still didn't work... could it be something wrong with my XML structure? or am I passing the wrong argument...
Can you parse the whole XML structure into an object and iterate on that?

Another approach that crossed my mind if the idea above doesnt work (but I dont know if it's possible, I have very little AS experience) is that:
XML -> PHP (transforms XML into something that can be read by AS, or direct AS code) -> AS (output from PHP is parsed by, or directly included in AS)
That's what I'm doing... the menuList is an XMLList object... and I'm using the for loop to iterate through it...
Kassem wroteThat's what I'm doing... the menuList is an XMLList object... and I'm using the for loop to iterate through it...
Again, I am no AS programmer, but "XMLList" implies that it's a single depth list. What i meant is parse it into a DOM object or multidimentional array (if there is such a thing).
Sorry if I'm not much help :)

Also... maybe it's a problem with variable scope?
If I wanted to check how many "item" nodes there are in the root xml I would type something like:
if(menu.item.length()>0) ...
rolf wrote
Kassem wroteThat's what I'm doing... the menuList is an XMLList object... and I'm using the for loop to iterate through it...
Again, I am no AS programmer, but "XMLList" implies that it's a single depth list. What i meant is parse it into a DOM object or multidimentional array (if there is such a thing).
Sorry if I'm not much help :)

Also... maybe it's a problem with variable scope?
XML object does parse the text into a DOM. XMLList is the way to retrieve a list of XML objects. Each of those can have it's one XMLLists. Hence a DOM.

@Kassem: You need to use:
        private function checkForChildren(node:XML):void
        {
            trace(node.item.length());
        }
AS has syntactic sugar for handling XML (based on E4X's handling of XMLs). If you want arbitrary levels, you will have to use recursive functions as well.

I had a demo I can send you soon.
rolf wrote
Kassem wroteThat's what I'm doing... the menuList is an XMLList object... and I'm using the for loop to iterate through it...
Again, I am no AS programmer, but "XMLList" implies that it's a single depth list. What i meant is parse it into a DOM object or multidimentional array (if there is such a thing).
Sorry if I'm not much help :)

Also... maybe it's a problem with variable scope?
oh ok... well yeah the xmlData variable I'm using is an XML object which refers to the whole XML structure (I guess). and then I used xmlData.item to generate the XMLList(menuList) which is just like you said a single depth list. Now, since not all of the top level nodes have children I need to check for the presence of child nodes and then iterate through them and parse them in an XMLList so I can manipulate them as I wish (P.S: I believe that's the right way of doing it, if any AS3.0 developer knows a better way plz tell me about it)
finally got it!
private function checkForChildren(node:XML):void
{
			
	trace(node.children().length());
			
}
Now I'll try to make it work and report back! :)
Those kind of errors suck :)
But hey, when it's a method, you gotta use parenthesis. When it's a property, I guess you can skip them.
Hard to spot thought, since AS doesn't give you a clue!