Парсер для обработки тагов

  • Автор темы Deadangel
  • Дата начала
Статус
Закрыто для дальнейших ответов.
D

Deadangel

#1
Всем привет,

прошу Вас помочь в одной деликатной ситуации. Ситуация такая:

есть некоторый текст из N символов. В этом тексте содержатся разные таги (<table>, <tr>, <td>, <img>, <a>). Нужно этот текст разделить на несколько равных частей, т.е сделать постраничный вывод для этого текста. Возникают такие ситуации, когда при разделении текста половина тага находится в одной части, другая половина находится в другой. Чтобы этого избежать, нужно обрабатывать эти таги. Может быть кто-нибудь подскажет, есть ли готовые решения подобных парсеров или же может кто делал что-то подобное. Буду признателен за любую информацию.


Спасибо.
 
M

MajestiC

#2
Первое что взбрело в голову (слишком много ограничений, наверное не подойдет):

Для начала делаешь так, чтобы участки (слова/тэги) разделенные пробелами/табуляциями не резались прямо в слове, и что-бы таблицы/ссылки не разрывались (то есть, если на странице есть таблица или ссылка, то таблица/ссылка не перескакивает частично на след. страницу). Реализовать это можно регулярками. Так вот делишь части.

Потом обрабатываешь (на-лету при выводе, или заранее):
Первая страница - ты должен закрыть все открытые тэги для корректного вывода:
Код:
	function closeTags($html)
{
#put all opened tags into an array
preg_match_all("#<([a-z]+)( .*)?(?!/)>#iU",$html,$result);
$openedtags=$result[1];

#put all closed tags into an array
preg_match_all("#</([a-z]+)>#iU",$html,$result);
$closedtags=$result[1];
$len_opened = count($openedtags);
# all tags are closed
if (count($closedtags) == $len_opened)
return $html;

$openedtags = array_reverse($openedtags);
# close tags
for($i=0;$i < $len_opened;$i++) 
{
if ($openedtags[$i] != 'hr' && $openedtags[$i] != 'br' && $openedtags[$i] != 'img')
{
if (!in_array($openedtags[$i],$closedtags))
{
$html .= '</'.$openedtags[$i].'>';
}
else
{
unset($closedtags[array_search($openedtags[$i],$closedtags)]);
}
}
}
return $html;
}
Функция конечно не сильно универсальна (лень было искать одиночные теги), но должна сработать =)
Потом по аналогии с ней делаешь функцию openTags который открывает закрытые (но не открытые) тэги.

В последующих страницах делаешь openTags, потом closeTags.

Как-то так. Может кто что-нибудь по-оригинальней придумает, но мне в данный момент лень :)
 
D

Deadangel

#3
Вот, например, текст на входе такой:

$html = '<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center"><tr><td><p>Уважаемые абоненты,
Предлагаем Вам воспользоваться услугой <b>"КОММУТИРУЕМЫЙ ДОСТУП В ИНТЕРНЕТ"</b> с использованием модемного пула 600-7000, число соединительных линий на котором увеличено до 6800.
За счёт хорошей связи модемного пула 600-7000 со всеми узлами Городской Телефонной Сети качество соединений существенно возрастет, а мощности нового модемного пула позволят обеспечить устойчивое подключение всех абонентов компании "КОМСТАР-Директ", пользующихся коммутируемым доступом.<p><img src="../ads.jpg" alt="" width="758" height="535" border="0"></p>
В целях работоспособности услуг: обратный вызов (call-back), дополнительные входные имена, а также для доступа абонентов из Московской области будут сохранены номера модемных пулов 105-5555, 995-5555 и 995-5556.</p></td></tr></table><table width="100%" border="0" cellspacing="0" cellpadding="0" align="center"><tr><td><p><img src="../ads.jpg" alt="" width="758" height="535" border="0"></p><p>Уважаемые абоненты,
Предлагаем Вам воспользоваться услугой <b>"КОММУТИРУЕМЫЙ ДОСТУП В ИНТЕРНЕТ"</b> с использованием модемного пула 600-7000, число соединительных линий на котором увеличено до 6800.
За счёт хорошей связи модемного пула 600-7000 со всеми узлами Городской Телефонной Сети качество соединений существенно возрастет, а мощности нового модемного пула позволят обеспечить устойчивое подключение всех абонентов компании "КОМСТАР-Директ", пользующихся коммутируемым доступом.
В целях работоспособности услуг: обратный вызов (call-back), дополнительные входные имена, а также для доступа абонентов из Московской области будут сохранены номера модемных пулов 105-5555, 995-5555 и 995-5556.</p></td></tr></table>';

При первом вырезании попадаем в тег <img> и получаем вот что:

$text = '<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center"><tr><td><p>Уважаемые абоненты,
Предлагаем Вам воспользоваться услугой <b>"КОММУТИРУЕМЫЙ ДОСТУП В ИНТЕРНЕТ"</b> с использованием модемного пула 600-7000, число соединительных линий на котором увеличено до 6800.
За счёт хорошей связи модемного пула 600-7000 со всеми узлами Городской Телефонной Сети качество соединений существенно возрастет, а мощности нового модемного пула позволят обеспечить устойчивое подключение всех абонентов компании "КОМСТАР-Директ", пользующихся коммутируемым доступом.<p><img src="../ads.jpg" alt="" ';

И как быть дальше ? Как искать теги ?
 
P

progstone

#4
если в тексте нету тега script то вполне можно считать тагом от '<' и до '>'
 
D

Deadangel

#5
А если в самом тексте встречаются символы? (<, >, <<, >> ...)
 
P

progstone

#6
значит обрабатывай в 2 этапа,
1)просто выделяй в динамически разрастаемый массив теги как от '<' до '>'(для надежности пропускай "<<" и ">>")
2)из полученных тегов определяй какие изи них действимтельно теги(понапиши всякие в блокноте и посмотри как ихи интерпретирует IE)
P.S сам уже такое реализовывал на Visual C++,пытался писать качалку сайтов.Нормально парсило html,но вот между тегами <script></script><noscript> пришлдось просто пропускать,а с современным подходом к сайто строительству ето не дело.
 
Статус
Закрыто для дальнейших ответов.