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

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">?

Подскажите, можно ли это реализовать на регэкспах? Если да, то был бы благодарен за выражение или за ссылки. Заранее благодарю.
 

que_bunt

Новичок
если после нужного </td> больше не будет </td> то можна воспользоватся жадностью квантификаторов.
 

SaNeK

Новичок
que_bunt
нет, будут они. Это же страница, там все, что угодно может быть...
 

vadim

Guest
SaNeK
Единственная проблема, так это то, что может вложенная таблица попасться, правильноя понял?? так как там td может появится
Можно тогда этот случай предусмотреть. Тое сть либо ищем просто закрытие td, либо ищем td с вложенной таблицей

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

Это просто пояснение моих мыслей, код естественно ещё не рабочий
 

zerkms

TDD infected
Команда форума
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: по идее списки тегов заполняются из спецификации - всё переписывать лениво, да и тебе не факт что нужны именно все ;)
 

vadim

Guest
SelenIT
мультипликатор то ещё никто не отменял, то есть {,100}
 

zerkms

TDD infected
Команда форума
vadim
хотя бы для интереса попробуй заставить работать своё регулярное выражение так, как это требуется в задании

ps: квантификатор
 

vadim

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

zerkms

TDD infected
Команда форума
vadim
так вот, попробуй свою мысль оформить в рабочий код
 
Сверху