Как включить каждый дочерний элемент дочернего элемента в вывод? PHP - PullRequest
0 голосов
/ 18 февраля 2012

У меня есть небольшое приложение, которое выполняет следующее:

  • позволяет пользователю загружать файл XML
  • анализирует файл XML в массив для работы с $ _SESSION
  • отображает список имен родительских элементов, которые пользователь может выбрать для просмотра
  • анализирует массив для отображения дочерних элементов выбранных родительских элементов

Проблема заключается в том, что каждый item может иметь детей, которые могут иметь детей, которые могут иметь детей ... и т. д. ... и это может продолжаться бесконечно.

Как можно включить каждого ребенка ребенка вокончательный вывод?

XML-файлы могут выглядеть примерно так:

<thing>
  <parents>
    <parent>
      <name>parent 1</name>
      <categories>
        <category>
          <name>category 1</name>
          <items>
            <item>
              <name>item 1 (gen 1)</name>
              <items>
                <item>
                  <name>sub-item 1 (gen 2)</name>
                  <items>
                    <item>
                      <name>sub-sub-item 1 (gen 3)</name>
                      ...this could continue forever..
                    </item>
                  </items>
                </item>
              </items>
            </item>
          </items>
        </category>
      </categories>
    </parent>
  </parents>
</thing>

Я проанализировал XML в массив с помощью PHP SimpleXML.Каждый файл должен иметь родительский элемент, категорию и дочерние элементы первого поколения.Следующий код анализирует эти 3 уровня структуры, но за пределами этого я потерян.

$output .= '<ul>';
foreach($xml['parents'] as $parent){
  $output .= '<li>'.$parent['name'].'</li>';
  foreach($parent['categories']['category'] as $category){
    $output .= '<li>'.$category['name'].'</li>';
    foreach($category['items']['item'] as $item){
      $output .= '<li>'.$item['name'].'</li>';
      // here is where the $item can have children w/ children
      // who can have children who can have children... etc... forever.
      // (i.e. $item['items']['item'] as $generation2_items++...)
      //
      // I want to add them as another <li></li>...
      //
      // How can you account for unknown # of children?
    }
  }
}
$output .= '</ul>';
echo $output;

Код $ выводит список, подобный следующему:

- parent 1
-- category 1
--- item 1 (gen 1)
---- sub item 1 (gen 2)
----- sub-sub item 1 (gen 3)
------- etc.
-------- etc.

Как определитьсколько дочерних элементов вглубь каждого элемента, а затем, как вы можете создать достаточное количество циклов для соответствующего анализа ... или итерации другим способом?

Спасибо за вашу помощь.

Решение

Решена рекурсивная функция PHP.Вот что я использовал, когда добрался до возможной бесконечной повторяющейся части:

function foo($element, $indent=0){
  $result .= '<li>';
  if($indent > 0){
    for($i=1;$i<=$indent;$i++){
      $result .= '&nbsp;&nbsp;&nbsp;&nbsp;';
    }
  }
  $result .= $element['name'].'</li>';
  if(isset($element['children']['child'])){
    $i++;
    foreach($element['children']['child'] as $child){
   $result .= foo($child, $i);
    }
  }
  return $result;
}    

$output .= foo($item);

Ответы [ 2 ]

3 голосов
/ 18 февраля 2012

Для этого вы можете использовать рекурсивную функцию .Каждый программист должен знать, как использовать рекурсию;если вы этого не сделаете: идите дальше и изучите это прямо сейчас!

Что вы в основном хотите сделать, это создать функцию, давайте назовем ее foo(), которая принимает один элемент в качестве входных данных.foo сделает две вещи:

  1. Выведите текущий элемент
  2. Для каждого дочернего элемента вызовите себя с дочерним элементом в качестве ввода.

Создание рекурсивногофункции, как я уже сказал, действительно полезны, и вы должны изучить и использовать этот инструмент.Например, вы можете отправить второй аргумент foo с глубиной рекурсии, чтобы вы могли выводить потомки с разными отступами.

1 голос
/ 18 февраля 2012

В псевдокоде рекурсивная функция обхода узла может выглядеть примерно так:

function traverse(node)
{
    print(node);

    if(node.hasChildren()) {
        foreach(node.children as child) {
            traverse(child);
        }
    }
}

Надеюсь, это поможет!:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...