使用数组值循环和构建HTML DOM


Loop and Build HTML DOM using array values

我很难理解如何调用特定的foreach命令将允许我调用以显示需求。

<?php
$html = array(
    array(
        'tag_name' => 'h1',
        'content' => 'My page title'
    ),
    array(
        'tag_name' => 'p',
        'attributes' => array(
            'class' => 'big shiny'
        ),
        'content' => 'Pizza is one of the main food groups. 5 out of 4 dentists recommend pizza over any other form of nutrition. Thou shalt eat thine pizza.'
    ),
    array(
        'tag_name' => 'label',
        'attributes' => array(
            'for' => 'like_pizza'
        ),
        'content' => 'Do you like pizza?'
    ),
    array(
        'tag_name' => 'input',
        'attributes' => array(
            'type' => 'checkbox',
            'id' => 'like_pizza',
            'name' => 'like_pizza',
            'checked' => 'checked'
        )
    )
);
?>

如何使用foreach循环输出以下HTML。

<h1>My Page Title</h1>
<p class="big shiny">Pizza is one of the main food groups. 5 out of 4 dentists recommend pizza over any other form of nutrition. Thou shalt eat thine pizza.</p>
<label for="like_pizza">Do you like pizza?</label>
<input type="checkbox" id="like_pizza" name="like_pizza" checked="checked">

首先请回顾一下这个http://php.net/manual/de/control-structures.foreach.php(只是为了教育)。

方法(与所有树状结构一样,因此,标记语言如HTML、XML和背后的任何数据表示)是使用递归。

因此,您只需要考虑第一级标记本身的求值,然后捕获异常情况。

<?php
$html = array(
    array(
        'tag_name'=>'h1',
        'content'=>'My page title'
    ),
    array(
        'tag_name'=>'p',
        'attributes'=>array(
            'class'=>'big shiny'
        ),
        'content'=>'Pizza is one of the main food groups. 5 out of 4 dentists recommend pizza over any other form of nutrition. Thou shalt eat thine pizza.'
    ),
    array(
        'tag_name'=>'label',
        'attributes'=>array(
            'for'=>'like_pizza'
        ),
        'content'=>'Do you like pizza?'
    ),
    array(
        'tag_name'=>'input',
        'attributes'=>array(
            'type'=>'checkbox',
            'id'=>'like_pizza',
            'name'=>'like_pizza',
            'checked'=>'checked'
        )
    )
);
?>

纠正你的缩进,看看你的格式:当然,根是一个只包含数组的数组。这些数组中的每一个都包含键<->值对,这些值对构成了一个标记的信息。

因此,您必须编写一个函数来处理信息并将其转换为标记字符串表示。

function formatTag($tag, $attributes, $content)
{
    $str = "<".$tag;
    foreach($attributes as $attrName => $attrValue)
    {
        $val = $attrValue;
        if(is_array($attrValue)) // Consider multiple class assignments!
          foreach($attrValue as $value)
             $val .= $value.' ';
        $str .= ' '.$attrName.'="'.$val.'"';
    }
    $str .= ">".$content."</".$tag.">";
    return $str;
}
function handleTagArray($arr) {
    if(!array_key_exists("tag_name"))
        throw new Exception("Invalid format!");
    $tag = $arr["tag_name"];
    $attributes = array_key_exists("attributes") ? $arr["attributes"] : "";
    $content = array_key_exists("content") ? $arr["content"] : "";
    if(is_array($content))
    {
        foreach($content as $child) // One tag could have multiple children!
        {
            if(is_array($child)) // Distinguish mixed children types tag or text here!
                $content .= handleTagArray($child);
            else 
                $content .= $child;
    }
    return formatTag($tag, $attributes, $content);
}

这个解决方案考虑到一个标签可以有多个子标签。

array ( 'tag_name'=> 'body',
        'content' => array (
                       array ( 'tag_name' => 'h1',
                               'content' => 'My page title' 
                       ),
                       array ( 'tag_name' => 'p',
                               'attributes' // ...
                     )
       );

该解决方案还考虑到<div id="test" class="testdiv noborder fullwidth">Test</div>这样的标签,即一个标签有多个类的可能性。你必须在你的数组结构中相应地写:

//...
array( 'tag_name' => 'div',
       'attributes' => array('id'=>'test', 'class'=>array('testdiv', 'noborder', 'fullwidth')), 
       'content' => 'Test' );

另外,考虑到默认情况下XML和HTML要求你有一个根节点,即第一个数组也应该包含标签信息,子数组应该包装在它的内容数组中。


编辑:根据@faino对array_key_exists的注释调整了我的代码。今天学了点新东西。D谢谢你!

编辑:添加了子类型标记<->文本的区别,参见代码!

像这样的东西会做到这一点,它有点粗糙,但这是一个很好的开始,你可以从中学习。查看array_key_exists和foreach文档以获得更好的理解和更多示例。

<?php
    $html = array(
        array(
            'tag_name'=>'h1',
            'content'=>'My page title'
        ),
        array(
            'tag_name'=>'p',
            'attributes'=>array(
                'class'=>'big shiny'
            ),
            'content'=>'Pizza is one of the main food groups. 5 out of 4 dentists recommend pizza over any other form of nutrition. Thou shalt eat thine pizza.'
        ),
        array(
            'tag_name'=>'label',
            'attributes'=>array(
                'for'=>'like_pizza'
            ),
            'content'=>'Do you like pizza?'
        ),
        array(
            'tag_name'=>'input',
            'attributes'=>array(
                'type'=>'checkbox',
                'id'=>'like_pizza',
                'name'=>'like_pizza',
                'checked'=>'checked'
            )
        )
    );
    // ECHO this function where needed
    function format_array($arr) {
        $output = "";
        foreach($arr as $inner) {
            $output .= "<" . $inner["tag_name"];
            if(array_key_exists("attributes", $inner)) {
                foreach($inner["attributes"] as $name => $val) {
                    $output .= " " . $name . "='"" . $val . "'"";
                }
            }
            $output .= ">";
            if(array_key_exists("content", $inner)) {
                $output .= $inner["content"] . "</" . $inner["tag_name"] . ">";
            }
        }
        return($output);
    }
    // Display the HTML
    echo(format_array($html));
?>

您只需调用该函数,并在您的HTML中返回该数组。

或者,您可以使用DOMDocument类并使用其有用的方法。考虑这个例子:

$html = array( array( 'tag_name'=>'h1', 'content'=>'My page title' ), array( 'tag_name'=>'p', 'attributes'=>array( 'class'=>'big shiny' ), 'content'=>'Pizza is one of the main food groups. 5 out of 4 dentists recommend pizza over any other form of nutrition. Thou shalt eat thine pizza.' ), array( 'tag_name'=>'label', 'attributes'=>array( 'for'=>'like_pizza' ), 'content'=>'Do you like pizza?' ), array( 'tag_name'=>'input', 'attributes'=>array( 'type'=>'checkbox', 'id'=>'like_pizza', 'name'=>'like_pizza', 'checked'=>'checked' ) ));
$dom = new DOMDocument();
$dom->loadHTML('<html></html>');
foreach($html as $tags) {
    $element = null;
    // tag
    if(isset($tags['tag_name'])) {
        $content = isset($tags['content']) ? $tags['content'] : '';
        $element = $dom->createElement($tags['tag_name'], $content);
    }
    // attributes
    if(isset($tags['attributes'])) {
        foreach($tags['attributes'] as $attribute_value => $value) {
            $attribute = $dom->createAttribute($attribute_value);
            $attribute->value = $value;
            $element->appendChild($attribute);
        }
    }
    $dom->appendChild($element);
}
echo $dom->saveHTML();

你可以使用递归函数

function display($data){
    foreach($data as $inner)
    {
        $ret = "<".$inner['tag'];
        if(is_array($inner['attributes'])                //check if there are attributes
        foreach($inner['attributes'] as $key => $value){
           $ret .= ' '.$key.'="'.$value.'"';
        }
        $ret .= ">".$inner['content'];
        if(is_array($inner['content'])) $ret .= display($inner['content']);     //call the function recursive for the nested ones
        $ret .= "</".$inner['tag'].">";
    }
    return $ret;
}

,像这样使用:

    echo display($html);