Разбор вложенных тегов в файле
Вопрос
Мне интересно - каков наиболее эффективный способ анализа чего-то вроде:
{{HEADER}}
Hello my name is {{NAME}}
{{#CONTENT}}
This is the content ...
{{#PERSONS}}
<p>My name is {{NAME}}.</p>
{{/PERSONS}}
{{/CONTENT}}
{{FOOTER}}
Конечно, в конце концов это должно быть чем-то вроде системы шаблонов, поэтому я планирую создать хэш-карту для "размещения поверх" шаблон, как-то так
$hash = array(
'HEADER' => 'This is a header',
'NAME' => 'David',
'CONTENT' => array('PERSONS' => array(array('NAME' => 'Heino'), array('NAME' => 'Sebastian')),
'FOOTER' => 'This is the footer'
);
Стоит отметить, что разделы " (теги, которые начинаются с #), могут повторяться более одного раза, и я думаю, что это меня расстраивает ...
Кроме того, любой раздел может содержать любое количество других разделов и обычных тегов ...
Итак .. как ты это сделал?
Решение
Является ли ожидаемый результат примерно таким:
Это заголовок
Здравствуйте, меня зовут Дэвид
This is the content ...
My name is Heino.
My name is Sebastian.
Это нижний колонтитул
<Ч>Как вы управляете отношением вложенных массивов в хэш-карте к повторяемым разделам в шаблоне? Каково реальное поведение шаблона должно быть? Если для несекционного элемента предоставляется массив, что он будет делать? Если элементу раздела предоставляется одно значение, будет ли он обрабатываться так же, как массив с единственным элементом (я так полагаю)?
Как бы то ни было, что касается парсера для шаблона (независимо от того, что вы в конечном итоге делаете с отображением данных) ... Что я хотел бы сделать, так это создать класс для каждого типа токена, включая универсальный для не содержание. Они наследуются от общего базового класса токенов с переопределяемыми методами Parse, Render и Map. Р>
Составьте схему своей диаграммы состояний и выясните, какие точки входа и выхода у вас есть для каждого состояния, а затем закодируйте это в структуру вызовов между токенами. В конце вы хотите получить перечисляемую коллекцию токенов, которая описывает ваш шаблон. Р>
Если у вас есть это в абстрактной форме, вы можете перебрать коллекцию, вызывая Map для токенов, чтобы назначить данные из хеш-карты в токены, а затем вызвать Render, чтобы преобразовать шаблон в его окончательную форму. Р>
Надеюсь, это поможет.
Другие советы
Самый эффективный способ - скомпилировать шаблон в код php. И просто включите скомпилированную версию.
Smarty Template Engine делает нечто подобное. Вы также можете посмотреть на источник smarty и проверить, как они анализируют теги.
Вы бы предпочли использовать что-то с существующим парсером, таким как XML или JSON, чтобы вам не приходилось писать свой собственный парсер, и чтобы другие могли легко писать документы для вашего парсера без использования специальных инструментов. Однако, если вы хотите написать свой собственный анализатор, вы, вероятно, захотите изучить использование Lex и Yacc .
Я бы пошел со сторонним парсером, потому что мне нравится работать умнее, а не усерднее, но если вы делаете это как упражнение или вы действительно хотите создать свой собственный механизм шаблонов (в PHP я полагаю из-за тега ), Я бы начал с рассмотрения шаблонов дизайна, в частности шаблона составного дизайна .
Составной шаблон часто используется в среде Java для таких вещей, как синтаксический анализ XML.
Я бы использовал что-то подобное в отдельном файле .php:
<?php echo $HEADER ?>
Hello my name is <?php echo $NAME?>
<div id="CONTENT">
This is the content ...
<?php foreach ($PERSONS as $PERSON) : ?>
<p>My name is <?php echo $PERSON['NAME']?>.</p>
<?php endforeach ?>
</div>
<?php echo $FOOTER ?>
И просто включите указанный выше файл в тот, в котором указаны ссылочные переменные.
Хотите верьте, хотите нет, PHP уже предоставляет все функции, которые системы шаблонов могут реализовать. Нет необходимости добавлять еще один уровень абстракции (и сложности) поверх PHP. Р>
Я использую DOM PHP для этого. Мой язык шаблонов - это просто HTML с идентификатором и атрибутами класса. Однако если вы хотите придерживаться своего плана, я бы использовал preg_replace_callback с шаблоном, который соответствует вашему синтаксису и функция обратного вызова, которая находит подходящую замену в вашем хэше, рекурсивно вызывая себя для элементов контейнера.