Николай С.
710 повідомлень
#17 років тому
Может кто чего умного подскажет?
Интересует возможность написать регулярку для следующей задачи: из кода

<div class="a">
<div class="b">
<div class="c">
текст
</div>
</div>
</div>


вытащить код

<div class="b">
<div class="c">
текст
</div>
</div>


Причем, вместо

<div class="c">
текст
</div>


может стоять все, что угодно (тоесть привязаться к внутреннему содержанию блока не получится).
Андрей Халецкий
3562 повідомлення
#17 років тому
|<div class="a">.?(<div class="b">.?<div class="c">*?</div></div>)</div>|is

Если текст.

|<div class="a">.?(<div class="b">.?<div class="c">.*?</div>.?</div>).?</div>|is

Если что угодно.


Не забываем про экранирование.
Николай С.
710 повідомлень
#17 років тому
SmartDesign, не, не то имелось ввиду. Я в первом посте написал, что привязаться к внутреннему содержанию нельзя (не известна внутренняя вложенность блоков div в блоке div class="b". Лучше всего конечный результат можно представить так: открываем xml файл в IE и сворачиваем произвольный item. Он сворачивается полностью, вне зависимости от наличия внутри таких же блоков с теми же именами.
Александр В.
276 повідомлень
#17 років тому
А где регулярными пользуешься?
Вот пример на php.
$matches - то что ищешь.
Или непременно надо сразу регуляркой только то что нужно вытащить ?

<?php
$text = "<div class=\"a\">\r\n<div class=\"b\">\r\n<div class=\"c\">\r\nтекст\r\n</div>\r\n</div>\r\n</div>\r\n";
preg_match_all("/<div*>(.*)<\/div>/is",$text,$matches);
print "<textarea style=\"width:1000px;height:800px\">";
print_r($matches);
print "</textarea>";
?>
Сергей М.
78 повідомлень
#17 років тому
Надо вытащить внутренний div 1-го уровня вложенности? Не указан язык. Если это Перл, то для этого есть динамические регекспы, которые разбирают произвольный уровень вложенности. На есть курс моих лекций по рег. выражениям Перл, в них есть этот раздел и примеры. А на books.ru продаётся моя книжка по этим лекциям. (Это так, в кач. саморекламы :-).
Если что, пиши на wait4sleeprambler.ru (если это надо для Перла!).
Александр В.
276 повідомлень
#17 років тому
Ну или, если всегда class="a":

"/(?<=(<div class=\"a\">)).*(?=<\/div>)/is"


Выражение не учитывает возможность отсутствия кавчек или лишних пробелов..... Но ИМХО это уже не сложно
Николай С.
710 повідомлень
#17 років тому
voral, эээхххх, тоже не подходит. Если в конец добавить лишние </div>, то будет резаться по ним, чего не требуется.
Serg31416, к сожалению php5.

Придется видимо отдельную функцию писать.
Александр В.
276 повідомлень
#17 років тому
Стоп, что значит лишние?
Поясни.... Проблему лишних можно решить. Только поясни, что ты понимаешь в данном примере под лишними?
Нужно чтоб было в результате одинаковое кол-во открывающих и закрывающих тегов?
Или ты имеешь ввиду что нужный блок может находится внутри более старшего блока? Тогда это тоже решается. Только необходимо пройтись от самого старшего. Легче всего рекурсией.

Ну на крайняк собираешь в массив все открывающие теги с позицией и закрывающие.... Но это уже больше php.
Александр В.
276 повідомлень
#17 років тому
Рекурсия. Делаешь пердыдущим выражение preg_match_all. Потом той же функциий каждый элемент в полученном массиве.... И так пока есть чего обрабатывать.
Второй вариант идти с самого глубокого уровня вложенности на верх по <div.*</div> (не разрешая встречаться открывающим и закрывающим внутри). С модификатором жадности. И постепенно заменяя "выкушенные куски" на временные переменные
Николай С.
710 повідомлень
#17 років тому
voral, спасибо за интерес к вопросу. Но рекурсия - это слишком долго. Скорее соберу позиции тегов в массив и пройдусь по нему.
Александр Веприк
5 повідомлень
#17 років тому
А здесь нужен именно RegExp?
Может быть, лучше использовать что-то наподобие DOM-парсера или XPath?
Николай С.
710 повідомлень
#17 років тому
Scratch, а они разве сработают с невалидным кодом?
Станислав Малкин
1410 повідомлень
#17 років тому
/<div class=\"a\">(*.?)<\/div>/i


Если я правильно понял задачу автора - то это должно помогать.
Александр В.
276 повідомлень
#17 років тому
Чем это отличается от моего предложения (кроме выражения в скобках) ?

И что означает последовательность *.?

* - 0 или более раз {0,}
. -любой символ
? - 0 или 1 раз {0,1}

Наверное все же .* достаточно? Или я не допонял мысль
Александр Веприк
5 повідомлень
#17 років тому
SolNikolay, XPath не должен бы.
А вот Dom parser частенько работает (по крайней мере тот который в PHP)
Вот, например:

$doc = new DOMDocument();
$doc->loadHTML("<html><body>Test<br></body></html>");
echo $doc->saveXML();


Посмотрите что он отдает -- валидный XHTML (XML). Который уже как вам угодно, парсером (или не выдавая -- через DOMXPath).
Александр Веприк
5 повідомлень
#17 років тому
Цитата ("ArtLab"):
/<div class=\"a\">(*.?)<\/div>/i


Если я правильно понял задачу автора - то это должно помогать.


Под этот паттерн подходит

<div class="a">
<div class="b">
<div class="c">
текст
</div>

(т.к. нежадный .* останавливается на первом же </div>.
Кстати, там закралась ошибка.

А если внутри этого "текст" находится еще один вложенный div... то вообще порвется.
Андрей Халецкий
3562 повідомлення
#17 років тому
Цитата ("SolNikolay"):
SmartDesign, не, не то имелось ввиду. Я в первом посте написал, что привязаться к внутреннему содержанию нельзя (не известна внутренняя вложенность блоков div в блоке div class="b". Лучше всего конечный результат можно представить так: открываем xml файл в IE и сворачиваем произвольный item. Он сворачивается полностью, вне зависимости от наличия внутри таких же блоков с теми же именами.

Так все-таки что нужно сделать? Выбрать содержимое верхних/нижних уровней вложенности дивов?
Николай С.
710 повідомлень
#17 років тому
SmartDesign, надо выбирать полностью блок html, вне зависимости от внутреннего и внешнего окружения.
К примеру из кода

<div class="a">
<div class="b">
<div class="c">
текст
</div>
</div>
</div>
<div class="a">
<div class="c">
еще текст
</div>
</div>
<div>
<div>
и еще текст
</div>
</div>


Вытащить блок

<div class="b">
<div class="c">
текст
</div>
</div>


или чуть подправив туже регулярку из того же кода вытащить

<div>
и еще текст
</div>


О DOM-парсере, XPath и SAX тоже думал, но думаю это все же медленнее, нежели регулярка. Вообще это и должно быть похоже на разбор xml через регулярные выражения.
Андрей Халецкий
3562 повідомлення
#17 років тому
ИМХО это не стоит делать чисто регулярками.

Делаем функцию которая будет считать вложенность блоков и запоминать текст который расположен внутри блока с вложенностью = 1.

Для этого понадобится 2 регулярки.
1 - определяет начало блока
2 - определяет конец блока.
Николай С.
710 повідомлень
#17 років тому
Цитата ("SmartDesign"):
ИМХО это не стоит делать чисто регулярками.

Делаем функцию которая будет считать вложенность блоков и запоминать текст который расположен внутри блока с вложенностью = 1.

Для этого понадобится 2 регулярки.
1 - определяет начало блока
2 - определяет конец блока.


Ну вот сейчас так и делаю, определяя позиции через preg_split. Хотя понадобится еще регулярка (функция), что бы переходить к номеру необходимого блока (просто для <div class="a"> и <div> функция определения начала блока должна быть одинаковая).