2011-06-14 35 views
1

我使用此模式'/(\{(\w+)\}(.*))?\{%(\w+)%\}((.*)\{\/(\w+)\})?/i'preg_match函數中提取模板中的標記。如何使用preg_match提取自定義標記

樣本模板:

<table id="middle" cellspacing="0px" cellpadding="0px"> 
    {middle} 
    <tr> 
     {left}<td>{%left%}</td>{/left} 
     <td>{%middle%}{%content%}</td> 
     {right}<td>{%right%}</td>{/right} 
    </tr> 
    {/middle} 
</table> 

如何確保start和每個標籤的end真正符合它的名字
在這個例子中middle標籤兩種middlecontent相匹配,同時它應該只是匹配middle標籤

回答

1

我認爲解決這個問題的最好方法是在幾個不同的步驟中做到這一點。

首先,您應該使用preg_replace_callback/(?>{([^}]+)})(.*)?{\/\1}/sim作爲正則表達式。這會找到頂級{tag} {/ tag}。 $匹配[2]將包含內容(不帶標籤),而$匹配1將包含標籤本身。

您應該創建一個遞歸調用的函數,以便在回調中再次調用$ matches [2],以便找到子項{tags},以防萬一。這就是你將如何穿過樹。

最後,您應該創建一個處理{%tag%}的第三個函數。我會再次使用preg_replace_callback並使用switch語句來處理標記名稱。

這應該指向正確的方向。

編輯:這是一個什麼樣上述我一個全功能的演示: \

<?php 

$content = <<<END 
{a} 
    {b}I like {%first%} {%last%} a {c}lot{/c}.{/b} 
{/a} 
END; 

echo find_tags($content); 

function find_tags($content) 
{ 
    return preg_replace_callback('/(?>{([^}]+)})(.*)?{\/\1}/sim', 'find_tags_callback', $content); 
} 

function find_tags_callback($matches) 
{ 
    // Find and process any children tag pairs. 
    $matches[2] = find_tags($matches[2]); 

    // Process the tags {%tag%}. 
    $matches[2] = preg_replace_callback('/{%([^%]+)%}/sim', 'process_tags', $matches[2]); 

    switch ($matches[1]) 
    { 
    case 'a': 
     $tag = 'div'; 

     break; 
    case 'b': 
     $tag = 'p'; 

     break; 
    case 'c': 
     $tag = 'b'; 

     break; 
    } 

    return '<'.$tag.'>'.$matches[2].'</'.$tag.'>'; 
} 

function process_tags($matches) 
{ 
    switch ($matches[1]) 
    { 
    case 'first': 
     return 'Francois'; 

     break; 
    case 'last': 
     return 'Deschenes'; 

     break; 
    } 
} 

// 

結果字符串爲:<div><p>I like Francois Deschenes a <b>lot</b>.</p></div>

+0

謝謝老兄,解決了我的問題 – Omid 2011-06-14 07:50:04

+0

不客氣! – 2011-06-14 18:06:43

0

1爲了確保封閉標籤({this} {/ this})與數據標籤({%this%})匹配,我相信但不確定,您需要隨附的if語句來測試返回的字符串。

我會使用preg_replace_callback函數,就像這樣:

<?php 
$str = '<template contents>'; 
$newstr = preg_replace_callback(
'/(\{(\w+)\}(.*))?\{%(\w+)%\}((.*)\{\/(\w+)\})?/i', 
'check', //<-- the function to send matches to 
$str); 
function check($matches){ 
    if($matches[1] == $matches[2] && $matches[1] == $matches[3]){ 
     /*Do Work*/ 
     return ''; //new formatted string to send back to the $newstr var 
    } 
} 
?> 

的preg_replace_callback函數發送發現作爲數組用於處理特定功能的任何比賽,然後返回從該函數的新格式的字符串。

+1

你不需要if語句。這樣做會導致許多無效匹配,特別是:{a} {b} {/ b} {/ a}將導致{a} {/ b}。您需要查看[正則表達式後向引用](http://www.regular-expressions.info/brackets.html)。看我的例子。如果標籤位於多行上,該解決方案也不起作用。 – 2011-06-14 06:57:09