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

时间:2014-06-20 06:39:32

标签: php

我很难理解如何调用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">

4 个答案:

答案 0 :(得分:2)

首先请审核此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'
        )
    )
);
?>

更正了缩进后,请查看您的格式: 当然,root是一个只包含数组的数组。这些数组中的每一个都包含组成一个标签信息的关键&lt; - &gt;值对。

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

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谢谢faino!


编辑:添加了儿童类型标签&lt; - &gt;之间的区别文字,见代码!

答案 1 :(得分:1)

这样的事情会起到作用,它有点粗糙,但它是你学习的好开始。查看array_key_existsforeach文档以获得更好的理解和更多示例。

<?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中回显它。

答案 2 :(得分:0)

你可以使用递归函数。

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);

答案 3 :(得分:0)

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

Sample Output

$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();