Recursively looping through objects, looking for ideas.

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
aluminumpork
Forum Newbie
Posts: 14
Joined: Mon Oct 24, 2005 8:54 pm

Recursively looping through objects, looking for ideas.

Post by aluminumpork »

Alright, I'm trying to write an xml helper class that can output xml from an object.

Here's the basic "xml_node" class:

Code: Select all

class xml_node {
   public $node_name;
   public $children;
}
Now that's a VERY simple version of the actual class, but it'll show what I'm trying to do.

And here's the basic construction of a very simple XML doc.

Code: Select all

$xml = new xml_node('brands');

$children[] = new xml_node('brand', 'Sipura', array("id" => 1));
$children[] = new xml_node('brand', 'LinkSys', array("id" => 2));
$children[] = new xml_node('brand', 'Apple', array("id" => 3));

$xml -> set_children($children);
The above code was just copied and pasted from my code, and so the getters and setters are used.
The print_r output of the above looks like:

Code: Select all

xml_node Object
(
    [node_name:private] => brands
    [attributes:private] => 
    [node_value:private] => 
    [children:private] => Array
        (
            [0] => xml_node Object
                (
                    [node_name:private] => brand
                    [attributes:private] => Array
                        (
                            [id] => 1
                        )

                    [node_value:private] => Sipura
                    [children:private] => 
                )

            [1] => xml_node Object
                (
                    [node_name:private] => brand
                    [attributes:private] => Array
                        (
                            [id] => 2
                        )

                    [node_value:private] => LinkSys
                    [children:private] => 
                )

            [2] => xml_node Object
                (
                    [node_name:private] => brand
                    [attributes:private] => Array
                        (
                            [id] => 3
                        )

                    [node_value:private] => Apple
                    [children:private] => 
                )

        )

)
So you can see how the object is setup.

What's the best way to loop through this, so that, when it starts, it creates the first (root) node, checks that node for children, if children exist, go to the first child, create that node, then check that node for children and so on. Once it finds no more children, go back to the last "branch" where children were found and move to the next child. It seems a simple idea to me, but I just can't wrap my head around it. I've tried a bunch of things, and saw the only solution as using a recursive function, but could only -sort of- get it working

I'm fairly new to OOP in general, so please excuse any stupid mistakes of mine in the above code.

Thanks!

User avatar
superdezign
DevNet Master
Posts: 4135
Joined: Sat Jan 20, 2007 11:06 pm

Post by superdezign »

Well, in the spirit of nodes, I'd suggest using a linked list tree, and recursively passing through it.
aluminumpork
Forum Newbie
Posts: 14
Joined: Mon Oct 24, 2005 8:54 pm

Post by aluminumpork »

Okay, thanks for tip. Not knowing much about linked lists, I looked it up and understand what they're about, but they seem rather linear. You mention linked list tree, which, by the name would seem to make more since for this problem. Any examples or other information on how I might accomplish this?
User avatar
superdezign
DevNet Master
Posts: 4135
Joined: Sat Jan 20, 2007 11:06 pm

Post by superdezign »

A linked tree is a list of trees of lists... Here:

Code: Select all

class CNode
{
    public
    $data,
    $nextNode,   // Node object
    $childTree;  // LinkedTree object
}

class CLinkedTree
{
    public
    $parentNode,  // Node object
    $firstChildNode;  // Node object
}

TraverseTree($tree, $level = 1)
{
    for($node = $tree->firstChildNode; $node->nextNode instanceof CNode; $node = $node->nextNode)
    {
        echo 'Level ' . $level . ': ' . print_r($node->data, true) . "<br />\n";
        if($node->childTree instanceof CLinkedTree)
        {
            TraverseTree($node->childTree, $level + 1);
        }
    }
}
Mind you, I just wrote this so there may be some errors. This should describe how it works to you, though.

Eventually, you'll want to place more method such as access get/set functions, and functions for adding/removing from the tree. You'll also want to implement a $prevNode in CNode and a $lastChildNode in CLinkedTree in order to allow your functions for adding to the tree to work without traversing the whole thing.
Post Reply