Hi, Something like this looks more elegant to me <?php $menuItems = array( array('id'=>1, 'title'=>'One', 'parent_id'=>0), array('id'=>2, 'title'=>'two', 'parent_id'=>0), array('id'=>3, 'title'=>'three', 'parent_id'=>0), array('id'=>4, 'title'=>'two.1', 'parent_id'=>2), array('id'=>5, 'title'=>'two.2', 'parent_id'=>2), array('id'=>6, 'title'=>'two.1.1', 'parent_id'=>4), array('id'=>7, 'title'=>'two.1.2', 'parent_id'=>4), array('id'=>8, 'title'=>'two.1.3', 'parent_id'=>4), array('id'=>9, 'title'=>'two.1.3.1', 'parent_id'=>8), array('id'=>10, 'title'=>'two.1.3.2', 'parent_id'=>8), array('id'=>11, 'title'=>'two.1.3.2.1', 'parent_id'=>10), array('id'=>12, 'title'=>'two.1.3.2.2', 'parent_id'=>10), array('id'=>13, 'title'=>'two.1.3.2.3', 'parent_id'=>10), ); class DomUnorderedListBuilder { private $items; private $processed; private $document; public function __construct(array $items) { $this->items = $items; } public function build() { $items = $this->items; $this->processed = array(); $this->document = new DOMDocument('1.0', 'utf-8'); $rootNode = $this->doBuild($items); $this->document->appendChild($rootNode); return $this->document; } private function getChildrenItemsOf($parent) { return array_filter($this->items, function(array $item) use ($parent) { return $item['parent_id'] === $parent; }); } private function doBuild(array $unprocessedItems) { $rootNode = $this->document->createElement('ul'); $this->processItems($unprocessedItems, $rootNode); return $rootNode; } private function processItems(array $unprocessedItems, DOMNode $parentNode) { foreach ($unprocessedItems as $item) { if ($this->isProcessed($item['id'])) continue; $this->markProcessed($item['id']); $liNode = $this->document->createElement('li', $item['title']); $parentNode->appendChild($liNode); $children = $this->getChildrenItemsOf($item['id']); if (!empty($children)) { $ulNode = $this->document->createElement('ul'); $this->processItems($children, $ulNode); $liNode->appendChild($ulNode); } } } private function isProcessed($id) { return isset($this->processed[$id]); } private function markProcessed($id) { $this->processed[$id] = true; } } $b = new DomUnorderedListBuilder($menuItems); $document = $b->build(); $document->formatOutput = true; echo $document->saveHTML(), PHP_EOL; On Wed, Jan 6, 2016 at 8:47 AM, Kevin Waterson <kevin.waterson@xxxxxxxxx> wrote: > Trying to create a menu based on results from an adjacency list and DOM. > > I can get it work with some nasty hacks with loadHTML in the constructor > and str_replace in the toString functions. > I was looking for something more elegant. > > http://pastie.org/10672688 > > Thanks > Kev >