joppe_ wrote:i don't think it's possible to do what i'm doing with simple iteration
It is always possible to convert recursion into iteration, and vice versa, though admittedly sometimes it is not simple, i.e., one may need an explicit stack to convert recursion to iteration.
In this case, it looks like you are effectively doing tail recursion in each branch. Not tested, but perhaps the recursion could be converted to:
function Load($xml)
{
$str = file_get_contents($xml);
$this->ExecuteLoad($str);
return true;
}
function ExecuteLoad($str)
{
$container =& $this;
for (;;)
{
$begin = strpos($str, "<");
$end = strpos($str, ">");
if (strlen($str) > 2 && $str{$begin+1} == "/") // closing tag </foo>
{
// continue after closing tag
$str = substr($str, $end+1);
$container &= $container->parentNode;
}
else if (!is_null($begin) && $end) // if nodes left
{
if ($str{$end-1} == "/") // empty node <foo/>
{
$name = substr($str, $begin+1, $end-$begin-2);
// append new empty node
$container->childNodes[] =& new MiniDOMNode($name, $container, "");
// continue after empty node
$str = substr($str, $end+1);
}
else if ($str{$end+1} == "<") // if no value
{
$name = substr($str, $begin+1, $end-$begin-1);
if ($str{$end+2} == "/") // empty node <foo></foo>
{
// append new empty node
$container->childNodes[] =& new MiniDOMNode($name, $container, "");
// continue
$str = substr($str, strpos($str,">",$end+2)+1);
}
else // inner node <foo><bar>...
{
// append new node
$newNode = new MiniDOMNode($name, $container, "");
$container->childNodes[] =& $newNode;
// continue in new node
$str = substr($str, $end+1);
$container =& $newNode;
}
}
else // node has value
{
$name = substr($str, $begin+1, $end-$begin-1);
$pos = strpos($str, "<", $end+1);
$value = substr($str, $end+1, $pos-$end-1);
$newNode = new MiniDOMNode($name, $container, $value);
$container->childNodes[] =& $newNode;
$str = substr($str, $pos);
$container =& $newNode;
}
}
else // no nodes left
{
break;
}
}
}
EDIT:
By the way, this looks wrong:
else if (!is_null($begin) && $end) // if nodes left
strpos() returns false, not null, if the search string cannot be found. Therefore, that line should be:
else if ($begin !== false && $end !== false) // if nodes left