2011-06-14 37 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