Googlebot
Googlebot

Reputation: 15673

foreach loop for creating a HTML markup from a PHP array

Imagine you have an array of HTML elements (in their appearance order) as

$array = array(
  1=>array( 'level' => 1, 'element' => '<div class="parent">'),
  2=>array( 'level' => 2, 'element' => '<div class="child">'),
  3=>array( 'level' => 3, 'element' => '<span class="child2">'),
  4=>array( 'level' => 2, 'element' => '<div class="child">'),
  5=>array( 'level' => 2, 'element' => '<div class="child">'),
  6=>array( 'level' => 3, 'element' => '<span class="child2">'),
  7=>array( 'level' => 4, 'element' => '<span class="child3">'),
);

How do you plan a foreach loop to find the places of the closing HTML tags to output a string as

<div class="parent">
    <div class="child">
        <span class="child2">
        <span>
    </div>
    <div class="child">
    </div>
    <div class="child">
        <span class="child2">
            <span class="child3">
            </span>
        </span>
    </div>
</div>

My attempt was something like

foreach($array as $e){

echo $e['element'];

$level = $e['level'];
    if($level<=$previous_level) {
    echo $closing; 
    $closing = '';
    }
$closing.= '</'. $element . '>'; // which comes from parsed $e['element'];

$previous_level = $level;
}

Upvotes: 3

Views: 1363

Answers (2)

Dharman
Dharman

Reputation: 33238

Here is my solution using recursive function:

$array = array(
    1 => array('level' => 1, 'element' => '<div class="parent">', 'parsedElement' => 'div'),
    2 => array('level' => 2, 'element' => '<div class="child">', 'parsedElement' => 'div'),
    3 => array('level' => 3, 'element' => '<span class="child2">', 'parsedElement' => 'span'),
    4 => array('level' => 2, 'element' => '<div class="child">', 'parsedElement' => 'div'),
    5 => array('level' => 2, 'element' => '<div class="child">', 'parsedElement' => 'div'),
    6 => array('level' => 3, 'element' => '<span class="child2">', 'parsedElement' => 'span'),
    7 => array('level' => 4, 'element' => '<span class="child3">', 'parsedElement' => 'span'),
);

function displayTree(&$tree, $level = 1) {
    if (!$tree) {
        return;
    }
    $el = array_shift($tree); // get the current element
    echo $el['element'];
    if ($tree && $tree[0]['level'] > $level) {
        // if the next item is a child of this then increase the level and process the sub-tree
        displayTree($tree, $level+1);
    }
    echo '</'. $el['parsedElement'] . '>';
    if ($tree && $tree[0]['level'] < $level) {
        return; // go back to the parent
    }
    displayTree($tree, $el['level']); // process the next sibling
}
displayTree($array);

Output:

<div class="parent">
    <div class="child">
        <span class="child2"></span>
    </div>
    <div class="child"></div>
    <div class="child">
        <span class="child2">
            <span class="child3"></span>
        </span>
    </div>
</div>

Upvotes: 3

LF-DevJourney
LF-DevJourney

Reputation: 28529

You can do it with stack,

$array = array(
    1=>array( 'level' => 1, 'element' => '<div class="parent">'),
    2=>array( 'level' => 2, 'element' => '<div class="child">'),
    3=>array( 'level' => 3, 'element' => '<span class="child2">'),
    4=>array( 'level' => 2, 'element' => '<div class="child">'),
    5=>array( 'level' => 2, 'element' => '<div class="child">'),
    6=>array( 'level' => 3, 'element' => '<span class="child2">'),
    7=>array( 'level' => 4, 'element' => '<span class="child3">'),
);

$result = "";
$tags = [];    // stack to store node end tag
$levels = [];  // stack to store node level
foreach($array as $tag){

    $level = $tag["level"];
    $element = $tag["element"];

    while(end($levels) >= $level){ // pop all Sibling and their child
        array_pop($levels);
        $result .= array_pop($tags);
    }

    $result .= str_pad("",$level-1,"\t") . $element . "\n";
    array_push($tags, str_pad("",$level-1,"\t") . "</" .substr($element,1,strpos($element," ")-1) . ">\n");
    array_push($levels,$level);
}
while(end($levels)){
    array_pop($levels);
    $result .= array_pop($tags);
}
echo $result;

And the result,

php test.php
<div class="parent">
        <div class="child">
                <span class="child2">
                </span>
        </div>
        <div class="child">
        </div>
        <div class="child">
                <span class="child2">
                        <span class="child3">
                        </span>
                </span>
        </div>
</div>

Upvotes: 3

Related Questions