Удаление комментариев в формате HTML с помощью PHP, но уход из условий

В настоящее время я использую PHP и регулярное выражение, чтобы исключить все комментарии HTML со страницы. Скрипт работает хорошо … слишком хорошо. Он удаляет все комментарии, включая мои условные комментарии в. Вот что у меня есть:

<?php function callback($buffer) { return preg_replace('/<!--(.|\s)*?-->/', '', $buffer); } ob_start("callback"); ?> ... HTML source goes here ... <?php ob_end_flush(); ?> 

Поскольку мое регулярное выражение не слишком жарко, у меня возникают проблемы с попыткой выяснить, как изменить шаблон, чтобы исключить условные комментарии, такие как:

 <!--[if !IE]><!--> <link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen" /> <!-- <![endif]--> <!--[if IE 7]> <link rel="stylesheet" href="/css/ie7.css" type="text/css" media="screen" /> <![endif]--> <!--[if IE 6]> <link rel="stylesheet" href="/css/ie6.css" type="text/css" media="screen" /> <![endif]--> 

ура

Solutions Collecting From Web of "Удаление комментариев в формате HTML с помощью PHP, но уход из условий"

Поскольку комментарии не могут быть вложены в HTML, регулярное выражение может выполнять эту работу теоретически. Тем не менее, использование какого-то синтаксического анализа было бы лучшим выбором, особенно если ваш вход не гарантированно хорошо сформирован.

Вот моя попытка. Чтобы соответствовать только нормальным комментариям, это сработает. Это стало настоящим монстром, извините за это. Я тестировал его довольно широко, кажется, все хорошо, но я не даю никаких гарантий.

 <!--(?!\s*(?:\[if [^\]]+]|<!|>))(?:(?!-->).)*--> 

Объяснение:

 <!-- #01: "<!--" (?! #02: look-ahead: a position not followed by: \s* #03: any number of space (?: #04: non-capturing group, any of: \[if [^\]]+] #05: "[if ...]" |<! #06: or "<!" |> #07: or ">" ) #08: end non-capturing group ) #09: end look-ahead (?: #10: non-capturing group: (?!-->) #11: a position not followed by "-->" . #12: eat the following char, it's part of the comment )* #13: end non-capturing group, repeat --> #14: "-->" 

Шаги № 02 и № 11 имеют решающее значение. # 02 гарантирует, что следующие символы не указывают условный комментарий. После этого в # 11 убедитесь, что следующие символы не указывают конец комментария, а # 12 и # 13 – фактическое совпадение.

Примените с помощью «глобальных» и «доновых» флагов.

Чтобы сделать противоположное (соответствие только условным комментариям), это будет примерно так:

 <!(--)?(?=\[)(?:(?!<!\[endif\]\1>).)*<!\[endif\]\1> 

Объяснение:

 <! #01: "<!" (--)? #02: two dashes, optional (?=\[) #03: a position followed by "[" (?: #04: non-capturing group: (?! #05: a position not followed by <!\[endif\]\1> #06: "<![endif]>" or "<![endif]-->" (depends on #02) ) #07: end of look-ahead . #08: eat the following char, it's part of the comment )* #09: end of non-capturing group, repeat <!\[endif\]\1> #10: "<![endif]>" or "<![endif]-->" (depends on #02) 

Опять же, применитесь к «глобальным» и «дольным» флагам.

Шаг № 02 из-за синтаксиса с раскрытием нижнего уровня, см. «MSDN – О условных комментариях» .

Я не совсем уверен, где пробелы разрешены или ожидаются. Добавьте \s* к выражению, где это необходимо.

Если вы не можете заставить его работать с одним регулярным выражением или вы хотите сохранить больше комментариев, вы можете использовать preg_replace_callback . Затем вы можете определить функцию для обработки комментариев отдельно.

 <?php function callback($buffer) { return preg_replace_callback('/<!--.*-->/U', 'comment_replace_func', $buffer); } function comment_replace_func($m) { if (preg_match( '/^\<\!--\[if \!/i', $m[0])) { return $m[0]; } return ''; } ob_start("callback"); ?> ... HTML source goes here ... <?php ob_end_flush(); ?> 

Таким образом, это лучшее решение:

 <?php function callback($buffer) { return preg_replace('/<!--[^\[](.|\s)*?-->/', '', $buffer); } ob_start("callback"); ?> ... HTML source goes here ... <?php ob_end_flush(); ?> 

Он удаляет все комментарии и оставляет условные обозначения, за исключением верхней:

 <!--[if !IE]><!--> <link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen" /> <!-- <![endif]--> 

где дополнительная проблема вызывает проблему.

Если кто-нибудь может предложить регулярное выражение, которое учитывает это, и оставить это условие на месте, тогда это будет идеально.

Решение Tomalak выглядит неплохо, но, как новичок, и никаких дополнительных рекомендаций я не знаю, как его реализовать, хотя я бы хотел попробовать, если кто-нибудь сможет уточнить, как его применять?

благодаря

Я не уверен, понравится ли PHP регулярному выражению следующее: но попробуйте этот шаблон:

 '/<!--(.|\s)*(\[if .*\]){0}(.|\s)*?-->/' 

Что-то вроде этого может работать:

 /<!--[^\[](.|\s)*?-->/ 

Это то же самое, что и у вас, кроме того, что он игнорирует комментарии, имеет открытую скобку сразу после тега начала комментария.