正则表达式,用于解析HTML中的模板块

时间:2014-01-07 03:25:18

标签: php regex parsing

我的HTML文件中有以下块

<!-- BEGIN user_details -->
<h1>{firstname} {lastname}</h1>
<!-- FINISH user_details -->
上面的

user_details是一个包含如下数据的数组:

$user_details = array(
    0 => array('firstname' => 'Hercules', 'lastname' => 'Zeus'),
    1 => array('firstname' => 'Jesus', 'lastname' => 'Christ'),
    2 => array('firstname' => 'John', 'lastname' => 'Smith'),
    3 => array('firstname' => 'Goerge', 'lastname' => 'Bush')
);

还有其他块具有不同的BEGIN / FINSIH数组名称和不同的{elements}所以,我需要一个正则表达式,它将遍历整个文件并查找像那样的块,然后遍历其中的每个值并用实际值替换它们......

我的最终输出应该是:

<!-- user_details -->
<h1>Hercules Zeus</h1>
<h1>Jesus Christ</h1>
<h1>John Smith</h1>
<h1>George Bush</h1>
<!-- /userdetails -->

<h1>…</h1>标记未修复,在某些块中我使用<li></li>等。

我现在有了这段代码:

$search_in = file_get_contents('path/to/my/html/file/');
$search_for = "#<!-- BEGIN (.*?) -->(.+?)<!-- FINISH (.*?) -->#si";
if (!preg_match($search_for, $search_in, $return)) {
    return NULL;
}

$return = preg_replace("#<!-- BEGIN (.*?) -->", "", $return[0]);
$return = preg_replace("<!-- FINISH (.*?) -->#si", "", $return);
return var_dump($return);

//Look for anything enclosed in curly brackes like so {something}
    if(!preg_match_all("/{([^}]*)}/", $search_in, $matches)) {
        return NULL;
    }
    //Return all occurrences of {something} in an array for use later
    foreach($matches[0] as $value) {
        $_args[] = $value;
    }

但第一个不是var_dump任何数据,只有NULL,而且我知道上面的所有内容都是有效数据。我收到这些错误:

Notice: Undefined index: firstname in /home/content/v/i/r... on line 96
Notice: Undefined index: lastname in /home/content/v/i/r... on line 96

我不想使用像codeIgniter,cakePHP,Zend等框架。

2 个答案:

答案 0 :(得分:1)

function expand_template_blocks($matches) {
    $name = $matches[1];
    if (!isset($GLOBALS[$name])) {
        trigger_error("$name block has no input values");
        return "<!-- ERROR: $name -->";
    }
    $values = $GLOBALS[$name];
    $template_body = $matches[2];
    $expanded = '';
    foreach ($values as $item) {
        $expanded .= preg_replace_callback(
            "#{([^}]*)}#",
            function($m) use ($item) {
                // If an unknown key is found, the placeholder is left untouched.
                return isset($item[$m[1]]) ? $item[$m[1]] : $m[0];
            },
            $template_body
        );
    }
    return "<!-- $name -->$expanded<!-- /$name -->";
}
function process_file($path) {
    $source = file_get_contents($path);
    $block_template = '#<!-- BEGIN (.*?) -->(.+?)<!-- FINISH \1 -->#si';
    return preg_replace_callback($block_template, 'expand_template_blocks', $source);
}

echo process_file('path/to/my/html/file/');

每个块模板匹配都传递给expand_template_blocks并由其输出替换。块名称用于获取该名称的全局数组。此数组的每个项目都用作关联数组来实例化模板 - 占位符将替换为项目中的相应值。所有模板实例都是连接在一起的。

由于anonymous function使用,这需要PHP 5.3.0。这可以使用create_function进行解决。

答案 1 :(得分:0)

所以,看起来您基本上需要分别匹配{firstname}{lastname},然后根据您的数组插入值,对吗?

如果是这样的话,这是一个非常基本的正则表达式,也许太基本 ......

这是你要使用的表达式......

(\{firstname\}).*?(\{lastname\})

如果您需要指定仅在<h1><li>标记内找到它们:

<(?:h1|li)[^>]*>(\{firstname\}).*?(\{lastname\})</(?:h1|li)>