Регулярное выражение (в PHP), чтобы соответствовать и не являются объектами HTML
Вот цель: заменить все автономные амперсанды на & amp; но НЕ заменяйте те, которые уже являются частью сущности HTML, такие как & nbsp;.
Я думаю, что мне нужно регулярное выражение для PHP (предпочтительно для функций preg_), которое будет соответствовать только отдельным амперсандам. Я просто не знаю, как это сделать с preg_replace.
5 ответов
Вы всегда можете бежать html_entity_decode
прежде чем бежать htmlentities
? Работает, если только вы не хотите использовать амперсанды (и даже тогда вы можете играть с параметрами набора символов).
Гораздо проще и быстрее, чем регулярное выражение.
РНР htmlentities()
имеет double_encode
аргумент для этого.
Если вы хотите делать подобные вещи в регулярных выражениях, тогда полезны отрицательные утверждения:
preg_replace('/&(?![a-z#]+;)/i','&',$txt);
Росс привел меня к хорошему ответу. Вот код, который, кажется, работает довольно хорошо. До сих пор.:-) Цель, опять же, конвертировать HTML в XML, в частности описания для RSS-каналов. В кратком тестировании, которое я провел до сих пор (с некоторыми довольно причудливыми данными), я смог взять строки, обернутые в CDATA, и развернуть их. Проходит валидационные испытания. Спасибо, Росс.
//decode all entities
$string=html_entity_decode($string,ENT_COMPAT,'UTF-8');
//entity-encode only &<> and double quotes
$string=htmlspecialchars($string,ENT_COMPAT,'UTF-8');
Другие - хорошие предложения, и, возможно, это лучший способ сделать это. Но я подумал, что постараюсь ответить на вопрос в том виде, в котором он был задан - лишь бы привести пример регулярных выражений.
Ниже приводится специальная разобранная форма, допустимая в некоторых двигателях. Конечно, странным является то, что механизм, который позволяет регулярным выражениям с комментариями, позволяет использовать другие упрощенные выражения, но не как общий. Я оставлю эти упрощенные выражения в скобках в комментариях.
& # an ampersand
( \# # a '#' character
[1-9] # followed by a non-zero digit,
[0-9]{1,3} # with between 2 and 4 (\d{1,3} or \p{IsDigit}{1,3})
| [A-Za-z] # OR a letter (\p{IsAlpha})
[0-9A-Za-z]+ # followed by letters or numbers (\p{IsAlnum}+)
)
; # all capped with a ';'
Вы могли бы даже добавить туда кучу ожидаемых объектов, чтобы помочь сканеру регулярных выражений.
& # an ampersand
( amp | apos | gt | lt | nbsp | quot
# standard entities
| bull | hellip | [lr][ds]quo | [mn]dash | permil
# some fancier ones
| \# # a '#' character
[1-9] # followed by a non-zero digit,
[0-9]{1,3} # with between 2 and 4
| [A-Za-z] # OR a letter
[0-9A-Za-z]+ # followed by letters or numbers
)
; # all capped with a ';'
У меня была такая же проблема, изначально использовал:
$string = htmlspecialchars($string, ENT_QUOTES, "UTF-8", FALSE);
Но нужно было работать с PHP4 и набором CharSets, в итоге:
function htmlspecialchars_custom($string)
{
$string = str_replace("\x05\x06", "", $string);
$string = preg_replace("/&([a-z\d]{2,7}|#\d{2,5});/i", "\x05\x06$1", $string);
$string = htmlspecialchars($string, ENT_QUOTES);
$string = str_replace("\x05\x06", "&", $string);
return $string;
}
Это не идеально, но достаточно хорошо для моих нужд.