Как использовать preg_match для извлечения пользовательских тегов - PullRequest
1 голос
/ 14 июня 2011

я использую этот шаблон '/(\{(\w+)\}(.*))?\{%(\w+)%\}((.*)\{\/(\w+)\})?/i' для извлечения тегов из шаблона с помощью функции 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 соответствует обоим middle и content, тогда как он должен просто соответствовать тегу middle

Ответы [ 2 ]

1 голос
/ 14 июня 2011

Я думаю, что лучшим способом решения этой проблемы было бы сделать это в несколько разных шагов.

Во-первых, вы должны использовать preg_replace_callback с /(?>{([^}]+)})(.*)?{\/\1}/sim в качестве регулярного выражения.Это найдет верхний уровень {tag} {/ tag}.$ Match [2] будет содержать содержимое (без тегов), а $ match 1 будет содержать сам тег.

Вы должны создать функцию, которая вызывается рекурсивно, чтобы в обратном вызове, он вызывается снова в $ match [2], так что найдите потомки {теги} на случай, если их будет больше.Вот как вы пройдете по дереву.

Наконец, вы должны создать третью функцию, которая обрабатывает {% 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 голосов
/ 14 июня 2011

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 отправляет любые найденные совпадения в виде массива в указанную функцию для обработки, затем вы возвращаете новую отформатированную строку из этой функции.

...