2014-01-07 128 views
1

我在我的HTML文件正则表达式来解析模板块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数组名称和不同的{元素}所以,我需要一个正则表达式,它将遍历整个文件并查找像这样的块,然后遍历每个值并将其替换为实际值...

我最后的输出应该是:

<!-- 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或类似的框架。

+0

如果可能,请勿使用正则表达式。当然,有一个HTML解析库,可以通过元素进行导航。 – user2864740

+0

此外,user2864740,我自定义了我的块,所以我需要知道自己该怎么做,而我对DDM,smarty或类似项目不感兴趣,他们的文件太大我只需要几个函数 – JiggaJitsu

+0

我的意思是DOM上面不是DDM – JiggaJitsu

回答

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并由其输出替换。块名称用于获取该名称的全局数组。此数组中的每个项目都用作关联数组来实例化模板 - 占位符将用项目中的相应值替换。所有模板实例都被连接起来。

这需要PHP 5.3.0因为anonymous function的使用。这可以使用create_function解决。

+0

很酷,我现在要试试它,让你知道它是如何工作的。但是,不知道我是否在这里愚蠢或错过了什么,但是,您在哪里获得了您在expand_template-blocks函数中传递的$匹配?即函数expand_template_blocks($ matches) – JiggaJitsu

+0

@HilkiahMakemo'expand_template_blocks'在['preg_replace_callback]中用作[callback](http://php.net/manual/en/language.pseudo-types.php#language.types.callback) ''(http://php.net/manual/en/function.preg-replace-callback.php)在'process_file'里面。参数由'preg_replace_callback'提供。请参阅链接的手册页。 – Palec

+0

Palec,你是男人!!!!这很好用!我稍微修改了一下,但效果很好。我创建了一个类并使用了返回preg_replace_callback($ block_template,'self :: expand_template_blocks',$ source); – JiggaJitsu

0

所以,看起来你基本上需要分别匹配{firstname}{lastname},然后按照你的数组插入值,对吧?

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

这就是如果你需要,你会使用表达式...

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

指定它们仅存在于<h1><li>标签:

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

+0

感谢Vasili,但值'firstname'和'lastname'与每个数组都不同。另外,数组'user_details'与每个BEGIN/FINISH数据块不同。 – JiggaJitsu

+0

这使它超出了正则表达式的范围。你的代码需要搜索整个字符串/文件/页面(而不是逐行),在这种情况下,你会得到几个匹配,每个匹配有2个捕获组。您可能需要在获取它们时迭代每个匹配项/组,除非有更好的方式来做这件事,我不知道。 –