2014-01-07 158 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個捕獲組。您可能需要在獲取它們時迭代每個匹配項/組,除非有更好的方式來做這件事,我不知道。 –