有沒有一種簡單的方法可以將XML結構轉換為樹來存儲在數據庫中?

[英]Is there an easy way to convert an XML structure into a tree to store in a database?


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

具體來說,我想將XML結構轉換為數據庫的這種格式,以便我可以使用修改后的預訂樹遍歷:

database structure http://sitepointstatic.com/graphics/table02.gif

數據庫結構http://sitepointstatic.com/graphics/table02.gif

My XML structure looks something like this:

我的XML結構看起來像這樣:

<?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.

我已經創建了一個PHP腳本來遍歷XML結構並將我的名字丟棄,我只是在計算左右值時遇到了麻煩。我想我可能不得不改變我的遍歷邏輯,以便每次都跟着一個葉子,然后重新開始並重新開始,而不是每次都觸底每個分支。如果我能做到這一點,那么我認為左右計算會更容易。

My PHP script so far:

到目前為止我的PHP腳本:

<?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/

我正在使用此SitePoint文章作為參考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腳本更接近解決方案(並以更好的格式輸出更多(可能相關)的數字):

<?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>';

?>

2 个解决方案

#1


2  

The general approach here is to create an adjacency list (a tree), then traverse the tree assigning lft on your way down and rgt on your way up.

這里的一般方法是創建一個鄰接列表(一棵樹),然后在你下來的路上遍歷分配lft的樹,並在你的路上向上。

Assuming this xml:

假設這個xml:

<?xml version="1.0" standalone="yes"?>
<products>
<node><name>Top Membership</name>
  <node><name>Middle Membership</name>
    <node><name>Bottom Membership 1</name></node>
    <node><name>Bottom Membership 2</name>
      <node><name>Some content</name>
        <node><name>Specific content</name></node>
      </node>
    </node>
  </node>
</node>
</products>

The following code should do what you need.

以下代碼應該滿足您的需求。

$root = simplexml_load_string($xml);

function nested_set($parent, $rows=array(), $counter=1) {
    foreach ($parent->node as $node) {
        $row = array(
            'title'   => (string) $node->name,
            'parent' => (string) $parent->name,
            'lft'    => $counter++,
            'rgt'    => null,
        );
        list($rows, $counter) = nested_set($node, $rows, $counter);
        $row['rgt'] = $counter++;
        $rows[] = $row;
    }
    return array($rows, $counter);
}

function print_rows($rows) {
    $sep = '+'.str_repeat('-', 22).'+'.str_repeat('-', 22).'+'.str_repeat('-', 5).'+'.str_repeat('-', 5).'+'."\n";
    echo $sep;
    echo vsprintf("| %-20s | %-20s | %3s | %3s |\n", array_keys($rows[0]));
    echo $sep;
    foreach ($rows as $row) {
        echo vsprintf("| %-20s | %-20s | %3d | %3d |\n", array_values($row));
    }
    echo $sep;
}

list($rows, $counter) = nested_set($root);
// rows will be in reverse-traversal order
print_rows($rows);

Output will be:

輸出將是:

+----------------------+----------------------+-----+-----+
| title                | parent               | lft | rgt |
+----------------------+----------------------+-----+-----+
| Bottom Membership 1  | Middle Membership    |   3 |   4 |
| Specific content     | Some content         |   7 |   8 |
| Some content         | Bottom Membership 2  |   6 |   9 |
| Bottom Membership 2  | Middle Membership    |   5 |  10 |
| Middle Membership    | Top Membership       |   2 |  11 |
| Top Membership       |                      |   1 |  12 |
+----------------------+----------------------+-----+-----+

For more information on nested sets, see Joe Celko's work:

有關嵌套集的更多信息,請參閱Joe Celko的工作:

#2


0  

You should consider the XQuery PHP extension for doing this: http://www.zorba-xquery.com/site2/html/php.html

你應該考慮使用XQuery PHP擴展:http://www.zorba-xquery.com/site2/html/php.html


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2012/01/11/72f529270a81f3777def30867ae8c2d1.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com