_den_
написал 21 июня 2007 года в 13:30 (1097 просмотров)
Ведет себя
неопределенно; открыл 4 темы в форуме, оставил 8 комментариев на сайте.
Какзалось бы тривиальная задача — получить список открывающих HTML тэгов через регулярное выражение в preg_match_all(php) .
Но никак не могу составить шаблон, который бы исключал тэги вида . Т.е. не включать тэги, если перед закрывающей скобкой стоит «/».
Можь кто поделиться шаблончиком, если у кого завалялся? Буду очень и очень призщателен.
Последние комментарии
- OlegL, 17 декабря в 15:00 → Перекличка 21
- REDkiy, 8 июня 2023 года в 9:09 → Как «замокать» файл для юниттеста в Python? 2
- fhunter, 29 ноября 2022 года в 2:09 → Проблема с NO_PUBKEY: как получить GPG-ключ и добавить его в базу apt? 6
- Иванн, 9 апреля 2022 года в 8:31 → Ассоциация РАСПО провела первое учредительное собрание 1
- Kiri11.ADV1, 7 марта 2021 года в 12:01 → Логи catalina.out в TomCat 9 в формате JSON 1
ecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.
А добавить перед этой закрывающей «>» какое-нибудь »[^\/]«?
Вот неизящный Perl-овый пример (regexp’ы-то едины…):
<html>
<body>
text
tex</b>t</h2></div></body></html>~;
print «html is: „.$html.“\n»;
my $tags;
while ($html =~ /<\w>|<[^\/][^>]*[^\/]>/){
$html = $`.$’;
$tags .= $&;
}
print «tags are: „.$tags.“\n»;
Выполнение:
<body>
text
te<strong>x</b>t</h2></div></body></html>
</strong>
tags are:
</body>
</body>
</html>
Да в том-то и дело, что в переметрах самого тэга символ «/» может встречаться, скажем URL какой-нить, то есть срабатывать должно только если «/» стоит непосредственно перед >.
Так и поставь непосредственно перед > — только для одного символа! См. пример выше.
Там появляется «<\w>|», потому что иначе не будут учитываться теги типа »» (рассматриваются, минимум 2 символа, т.к. проверка на «без /» в начале и «без /» в конце).
p.s.
<body>
tex</a>t
te<strong>x</b>t</h2></div></body></html>
</strong>
tags are:
</body>
В принципе ясно, из этого можно получить нужный список, еще раз прогнав, и выдрав уже непосредственно имя тэгов.
Я пытался сделать это в одном выражении. Т.е получить список вида html,body,div,h2… (из твоего примера).
Вообще возможен такой вариант?
Спасибо за участие :).
Да легко:
<html>
<body>
tex</a>t
tex</b>t</h2></div></body></html>~;
print «html is: „.$html.“\n»;
my $tags;
while ($html =~ /<([^\/][^\s>]*)[^>]*(?<!(\/))>/){
$tags .= $1.«,»;
$html = $`.$’;
}
print «tags are: „.$tags.“\n»;
<html>
<body>
tex</a>t
tex</b>t</h2></div></body></html>
tags are: html,body,div,a,h2,b,
</body>
</html>
</body>
</html>
Блин крут… :), в принципе делает почти то-что нужно только вот не пойму почему не срабатывает второе условие на закрывающие тэги :
preg_match_all(’@<([^/][^\s>])[^>]*(?|</(\w+)[^>]>@’,$html,$tags) ;
Т.е. пытаюс получить спискок закрывающих и открывающих тэгов в порядке их следования, ну понятное дело чтобы провести простую проверку на корректность вложенности и т.д.
«</(\w+)[^>]>» — не очень корректно. Зачем тут и «\w+», и »[^>]«? Не будет работать для тега из одной буквы.
Можно и «</(\w+)>», и «</([^>]+)>». Но когда все вместе — получается не совсем то.
</(\w+)[^>]*> квалификатор '*' скушало почему-то.
В принципе может и не совсем корректно, но отрабатывает так как нужно, если не в составе вышеприведенного шаблона.
Да, тут <звездочка>текст<звездочка> заменяют на bold для «текст». Поэтому лучше такие вещи помещать в теги [code ]текст[/code ] (в обоих случаях, естественно, надо без пробелов между «code» и «]»).
А все равно: зачем »[^>]*» тут вообще? :-) Такой HTML не будет валидным…
В твоем случае, полагаю, не выцепляет закрывающие, потому что они хранятся уже не в $matches[0], как в случае с открывающим (regexp-то тут для всего один). Я бы сделал так:
<html>
<body>
tex</a>t
tex</b>t</h2></div></body></html>~;
print «html is: „.$html.“\n»;
my ($open_tags, $close_tags);
while ($html =~ /<([^\/][^\s>]*)[^>]*(?<!(\/))>/){
$open_tags .= $1.«,»;
$html = $`.$’;
}
while ($html =~ /<\/(\w+)>/){
$close_tags .= $1.«,»;
$html = $`.$’;
}
print «open tags are: „.$open_tags.“\n»;
print «close tags are: „.$close_tags.“\n»;
Получаем:
<html>
<body>
tex</a>t
tex</b>t</h2></div></body></html>
open tags are: html,body,div,a,h2,b,
close tags are: a,b,h2,div,body,html,
Логичнее все это кидать по массивам и тогда уже проверять. Ну, или на лету. По вкусу :-)
</body>
</html>
</body>
</html>
Да они в принципе по идее и так будут в двух массивах.
примерно:
tags[1] = array (’tag1\′,’tag2\′,»,’tag4\′);
tags[2] = array (»,»,’tag3\′,»);
В твоем примере мы теряем общую последовательность тегов, т.е. как узнать за каким открывающим идет какой закрывающи тэг. По этой причине я и пытаюсь загнать в единное выражение. Т.е. кроме наличия парных тегов хочется проверять и правльность их вложенности.
Вот такая штука в PHP:
Вернула мне:
<html>
<body>
[1] =>
[2] =>
[3] =>
[4] => </a>
[5] =>
[6] =>
[7] => </b>
[8] => </h2>
[9] => </div>
[10] => </body>
[11] => </html>
)
[1] => Array
(
[0] => html
[1] => body
[2] => div
[3] => a
[4] =>
[5] => h2
[6] => b
[7] =>
[8] =>
[9] =>
[10] =>
[11] =>
)
…
[3] => Array
(
[0] =>
[1] =>
[2] =>
[3] => a
[4] =>
[5] => b
[6] => h2
[7] => div
[8] => body
[9] => html
)
М?..
</body>
</html>
Да оно самое! С небольшими изменениями:
получилось как-раз то-что ожидал.
Просто ОГРОМНОЕ спасибо Dmitry.
К стати пока так и не понял как оно работает :), и покурю на досуге Фридла, что-ли…