I have some hierarchical data that I need to display in a series of nested ULs. For each element, I have a name, identifier, and depth value. Usually I just grouped these elements by depth, but I really need to create a tree structure with my data, for example: 
Here's my question: is there a good way to generate valid markup (I would love it if I could print it using the correct tab, but it will be difficult), where will my data be wrapped in nested UL? I already have a solution that works, but I get the only trick. Here is the code I have for this:
<?php include("includes/classes/Database.class.php"); $db = new Database(); $query = "SELECT COUNT(parent.Name) - 2 as level, node.Name AS Name, node.ID FROM Region AS node, Region AS parent WHERE node.LeftVal BETWEEN parent.LeftVal AND parent.RightVal and node.Name <> 'Earth' GROUP BY node.ID ORDER BY node.LeftVal"; $results = $db->executeQuery($query); ?> <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <?php $last_level = 0; ?> <ul id="regionTree"> <?php while ($row = mysql_fetch_assoc($results)) { $link = '<li>'.PHP_EOL.'<a href="addChild.php?parentid='.$row["ID"].'">'.$row["Name"]."</a>".PHP_EOL; $diff = $last_level - $row["level"]; if($diff == 0){ // Sibling echo ($row["level"] != 0) ? '</li>'.PHP_EOL.$link:$link; } elseif($diff < 0){ // Child $demoter = '<ul>'.PHP_EOL; for ($i=0; $i > $diff; $i--) { echo $demoter; } echo $link; } else{ // Parent $promoter = '</li>'.PHP_EOL.'</ul>'; for ($i=0; $i < $diff; $i++) { echo ($row["level"] != 0) ? $promoter.PHP_EOL."</li>":$promoter; } echo $link; } $last_level = $row["level"]; } ?> </li> </ul> </body> </html>
Any ideas?
:: Edit :: I created a pastebin with a created source that is not checked. Pastebin.com
:: EDIT 2 :: Here is the schema for the Region table. It is designed using a hybrid model of nested sets and an adjacency list model.
CREATE TABLE Region ( ID INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Stores the ID for the Region.', Name VARCHAR(45) NOT NULL COMMENT 'Stores the name of the Region', Region_Type VARCHAR(45) NOT NULL COMMENT 'Stores the Region type.', Parent INT COMMENT 'Stores the ID of the Parent Region', LeftVal INT NOT NULL, RightVal INT NOT NULL, PRIMARY KEY (ID) ) COMMENT 'Stores information about all Regions.' ENGINE=INNODB ROW_FORMAT=DEFAULT CHARACTER SET utf8 collate utf8_general_ci;
source share