RegExp'ы и "правильный" разбор html

  • Автор темы Автор темы SaNeK
  • Дата начала Дата начала

SaNeK

Новичок
RegExp'ы и "правильный" разбор html

Всем привет. Заранее извиняюсь, если вопрос такой уже поднимался - потыкался в поиск и не нашел.

Что есть: html-страница. В ней какая-то таблица. И ячейка с вида <td class="body">. Причем состав параметров этой ячейки может меняться (т.е. <td width="10" class="body"> или <td height="30" class="body"> и т.д.). Важен в этой ячеке именно css-класс. Причем 100%-уверенность, что такая ячейка на странице ВООБЩЕ ОДНА.

Что надо: выдернуть все, что стоит в этой ячейке, т.е. между тегами <td ... class="body"...></td>

Проблема: в этой ячейке могут быть и таблицы. Т.е. могут быть и </td>, которые закрывают вовсе не ячейку с данными (т.е. <td ... class="body"...>). Например, код такой:
<html>
.....
<td class="body">
<p>какой-то заголовок</p>
<table>
<tr>
<td>Какой-то текст</td>
</tr>
</table>
</td>
Так как мне выдернуть содержимое ячейки <td class="body">?

Подскажите, можно ли это реализовать на регэкспах? Если да, то был бы благодарен за выражение или за ссылки. Заранее благодарю.
 
если после нужного </td> больше не будет </td> то можна воспользоватся жадностью квантификаторов.
 
que_bunt
нет, будут они. Это же страница, там все, что угодно может быть...
 
SaNeK
Единственная проблема, так это то, что может вложенная таблица попасться, правильноя понял?? так как там td может появится
Можно тогда этот случай предусмотреть. Тое сть либо ищем просто закрытие td, либо ищем td с вложенной таблицей

(<td(.*)class=\"body\"(.*)>(.*)<\/td>) || (<td(.*)class=\"body\"(.*)>((.*)<table>(.*)<\/table>(.*))<\/td>)

Это просто пояснение моих мыслей, код естественно ещё не рабочий
 
PHP:
$string = '<td>not match</td><td a><td qqq><td class="body">   <table><a>lol</a><br><td>foo</td></table><br><img src="zzz">    </td></td>';

preg_match_all('#<td[^>]*class="body"[^>]*>.*</td>#', $string, $matches);

if (isset($matches[0][0])) {
    $string = $matches[0][0];
    
    $pair = array('a', 'table', 'b', 'tr'); // список необходимых парных тегов
    $pair = implode('|', $pair);
    
    $single = array('br', 'img'); // список необходимых одинарных тегов
    $single = implode('|', $single);

    preg_match_all("#<td[^>]*>((<(" . $pair . ")[^>]*>.*?</\\3>|<(?:" . $single . ")[^>]*/?>|[^<]+(/?td){0}|(?R))*)</td>#", $string, $matches);
    $result = $matches[1][0];
    var_dump($result);
}

ps: я решал спортивный вопрос - сделать всё это регом... думаю что в действительности гораздо проще реализовать всё это строковыми функциями.
pps: по идее списки тегов заполняются из спецификации - всё переписывать лениво, да и тебе не факт что нужны именно все ;)
 
SelenIT
мультипликатор то ещё никто не отменял, то есть {,100}
 
vadim
хотя бы для интереса попробуй заставить работать своё регулярное выражение так, как это требуется в задании

ps: квантификатор
 
zerkms
Я просто для примера привёл, и написал специально для подобных вопросов, что код-просто иллюстрация моих мыслей. А мысль была, надо просто все таблицы отлавливать (то есть (<table>(.*)</table>){,100} )
 
vadim
так вот, попробуй свою мысль оформить в рабочий код
 
Сверху