【问题标题】:PHP XML - How to build a tree of xml nodes that are at at same level with parent child relationshipPHP XML - 如何构建与父子关系处于同一级别的xml节点树
【发布时间】:2012-03-25 06:27:19
【问题描述】:

我正在尝试从文件中读取 xml 并像树一样显示它们。我正在使用 PHP,我想得到如下所示的输出。 xml文件的内容如下...

<Categories>

<Category>
  <Id>1</Id>
  <Name>Parent 1</Name>
  <ParentId>1</ParentId>
  <ParentName>Parent 1</ParentName>
</Category>
<Category>
  <Id>2</Id>
  <Name>Child 1</Name>
  <ParentId>1</ParentId>
  <ParentName>Parent 1</ParentName>
</Category>
<Category>
  <Id>3</Id>
  <Name>Child 2</Name>
  <ParentId>1</ParentId>
  <ParentName>Parent 1</ParentName>
</Category>
<Category>
  <Id>8</Id>
  <Name>Grand Child 1 -1</Name>
  <ParentId>2</ParentId>
  <ParentName>Child 1</ParentName>
</Category>

<Category>
  <Id>12</Id>
  <Name>Parent 2</Name>
  <ParentId>12</ParentId>
  <ParentName>Parent 2</ParentName>
</Category>

<Category>
  <Id>15</Id>
  <Name>Child 2-1</Name>
  <ParentId>12</ParentId>
  <ParentName>Parent 2</ParentName>
</Category>

  </Categories>
</CategoryList>

我想阅读这个 xml 文件(我知道如何阅读它)但我不能像下面这样格式化它......我将如何获取所有最顶层父节点的节点并获取这些父节点的子节点(使用递归或其他方法)

<ul>
<li>Parent 1
    <ul>
        <li> Child 1
            <ul>
                <li>Grand Child 1 -1</li>
            </ul>

        </li>
        <li> Child 2</li>
    </ul>

</li>
<li>Parent 2
    <ul>
        <li>Child 2-1 </li>
    </ul>

</li>

</ul>

任何帮助将不胜感激......

编辑*到目前为止我做了什么......

$xml= simplexml_load_string('myxmlstring');

get_categories($xml, 0);

function get_categories($xml, $id) {

    if ($id==0) 
        $Categories = $xml->xpath('Categories/Category[ParentId=Id]');
    else
        $Categories = $xml->xpath('Categories/Category[ParentId='.$id.' and Id!='.$id.']');

    echo '<ul id="catlist'.$id.'">';
    foreach($Categories as $Category) {
        echo "<li>ID: " . $Category->Id . "--Name: " . $Category->Name;
        get_categories($xml, $Category->Id);
        echo "</li>";

    }
    echo "</ul>";
}

现在我只想确认这是最佳解决方案。或者有人可以提出更好的主意...

【问题讨论】:

    标签: php xml-parsing


    【解决方案1】:

    ParentName 太多了,只放父ID就够了。

    由于您搜索每个节点,因此执行时间将为 O(N2),其中 N 是节点数。

    不过,有一个选项可以在线性时间内执行此操作:首先遍历数据并构建树结构(或在某种程度上),然后遍历该结构并根据它输出节点。

    Output buffering在这里也是一个不错的选择。

    // init
    $childrenReferences = array();
    $rootNodes = array();
    $xmlNodes = array();
    
    // gathering structure
    $cats = $xml->getElementsByTagName('Category');
    for ($i = 0; $i < $cats->length; $i++) {
        $cat = $cats[$i];
        $id = $children->Id;
        $parentId = $cat->ParentId;
        $xmlNodes[$id] = $cat;
        if ($parentId == $id) {
            $rootNodes []= $id;
            continue;
        }
        if (array_key_exists($parentId, $childrenReferences)) {
            $childrenReferences[$parentId] []= $id;
        } else {
            $childrenReferences[$parentId] = array($id);
        }
    
    }
    
    // output
    function out_nodes($nodes) {
        global $childrenReferences, $xmlNodes; // this is not required since php 5.3 or something about
        echo "<ul>";
        foreach ($nodes as $id) {
            $cat = $xmlNodes[$id];
            echo "<li>ID: " . $cat->Id . "--Name: " . $cat->Name;
            if (array_key_exists($id, $childrenReferences)) { // intermediate node
                out_nodes($childrenReferences[$id]);
            }
            echo "</li>";
        }
        echo "</ul>";
    }
    
    ob_start();
    out_nodes($rootNodes);
    ob_end_flush();
    

    代码可能无法运行,甚至无法编译,但你明白了。

    【讨论】:

      【解决方案2】:

      感谢 kirilloid.... 这对我很有帮助... 我正在使用经过一些修改的代码... xml 来自 curl 并且我知道 ParentName 过多,但我无法控制它。这是最终的代码......

      $childrenReferences = array();
      $rootNodesIDs = array();
      $xmlNodes = array();
      
      $dom = new DOMDocument;
      $dom->loadXML($xml);
      
      $Categories = $dom->getElementsByTagName('Category');
      $length = $Categories->length;
      
      for ($i = 0; $i < $length; $i++) {
          $cat = $Categories->item($i);           //Get the DOMNode 
          $id = $cat->getElementsByTagName('Id')->item(0)->nodeValue;
          $parentId = $cat->getElementsByTagName('ParentId')->item(0)->nodeValue;
          $xmlNodes[$id] = $cat;      
      
          if ($parentId == $id) {
              $rootNodesIDs []= $id;
              continue;
          }
      
          if (array_key_exists($parentId, $childrenReferences)) {
              $childrenReferences[$parentId] []= $id;         
          } else {
              $childrenReferences[$parentId] = array($id);
          }
      }
      
      function out_nodes($rootids) {
          global $childrenReferences, $xmlNodes;
      
          echo "<ul>";
          foreach ($rootids as $id) {
              $cat = $xmlNodes[$id];
              echo "<li>ID: " . $cat->getElementsByTagName('Id')->item(0)->nodeValue . "--Name: " . $cat->getElementsByTagName('Name')->item(0)->nodeValue;
              if (array_key_exists($id, $childrenReferences)) { // intermediate node
                  out_nodes($childrenReferences[$id]);
              }
              echo "</li>";
          }
          echo "</ul>";
      }
      
      ob_start();
      out_nodes($rootNodesIDs);
      ob_end_flush();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多