Specifically, I want to convert the XML structure into this format for the database so that I can use modified preorder tree traversal:

(source: sitepointstatic.com)
My XML structure looks something like this:
<?xml version="1.0" standalone="yes"?>
<products>
<node>
<name>Top Membership</name>
<node>
<name>Middle Membership</name>
<node>
<name>Bottom Membership</name>
<node>
<name>Some content</name>
<node>
<name>Specific content</name>
</node>
</node>
</node>
</node>
</node>
I’ve made a PHP script to traverse the XML structure and dump me out the names, I’m just having trouble working out the left and right values. I think I probably have to change my traversal logic so that it’s followed down to a single leaf each time, then goes back up and starts again, rather than bottoming each entire branch each time. If I could do this then I think it would be easier to calculate left and right.
My PHP script so far:
<?php
$node = new SimpleXMLElement(file_get_contents('products.xml'));
echo '<pre>';
function getRowData($node, $depth)
{
//Not a leaf
if(isset($node->node))
{
echo $node->name."\t\t\t($depth) parent, children: ".count($node->children())."\n";
foreach($node->node as $n)
getRowData($n, $depth + 1);
}
else //It's a leaf
echo $node->name."\t\t\t($depth) leaf\n";
}
getRowData($node->node, 1);
echo '</pre>';
?>
I’m using this SitePoint article for reference http://www.sitepoint.com/hierarchical-data-database-2/
Edit:
Revised PHP script which is closer to a solution (and outputs in a better format with more (possibly relevant) numbers):
<?php
$node = new SimpleXMLElement(file_get_contents('products.xml'));
echo '<table border="1">';
echo '
<tr>
<th>Name</th>
<th>Depth</th>
<th>Child num</th>
<th>Children</th>
<th>Ancestors</th>
<th>Total siblings</th>
<th>"Left"</th>
<th>Parent "Left"</th>
</tr>';
function getRowData($node, $depth = 1, $child_num = 1, $prior_nodes = 0, $sibling_total = 0, $parent_left = 0)
{
echo '<tr>';
echo '
<td>'.$node->name."</td>
<td>$depth</td>
<td>$child_num</td>
<td>".(count($node->children()) - 1)."</td>
<td>$prior_nodes</td>
<td>$sibling_total</td>";
$left = $parent_left + ($child_num == 1 ? 1 : ($child_num * 2) - 1);
echo "<td>$left</td>";
echo "<td>$parent_left</td>";
echo '</tr>';
$child_num = 1;
foreach($node->node as $n)
{
getRowData(
$n,
$depth + 1,
$child_num++,
$prior_nodes + (count($node->children()) - 1),
(count($node->children()) - 1),
$left
);
}
}
getRowData($node->node);
echo '</table>';
?>
The general approach here is to create an adjacency list (a tree), then
traverse the tree assigning
lfton your way down andrgton your way up.Assuming this xml:
The following code should do what you need.
Output will be:
For more information on nested sets, see Joe Celko’s work: