Вот цель: заменить все автономные амперсанды на & amp; но НЕ заменяют те, которые уже являются частью HTML-объекта, такого как & nbsp ;.
Я думаю, мне нужно регулярное выражение для PHP (желательно для preg_ functions), которое будет соответствовать только автономным амперсандам. Я просто не знаю, как это сделать с preg_replace.
Вы всегда можете запустить html_entity_decode
перед запуском htmlentities
? Работает, если только вы не хотите использовать амперсанды (и даже тогда вы можете играть с параметрами кодировки).
Гораздо проще и быстрее, чем регулярное выражение.
PHP htmlentities()
имеет аргумент double_encode
для этого.
Если вы хотите делать что-то подобное в регулярных выражениях, то отрицательные утверждения полезны:
preg_replace('/&(?![az#]+;)/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');
Другие – хорошие предложения, и это может быть лучший способ сделать это. Но я подумал, что постараюсь ответить на вопрос, как было задано, – только для того, чтобы предоставить пример регулярного выражения.
Ниже приведена специальная взорванная форма, разрешенная в некоторых двигателях. Конечно, странно, что движок, который позволяет прокомментированные регулярные выражения допускать другие упрощенные выражения, но не как общие. Я добавлю эти упрощенные выражения в parens в комментарии.
& # 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("/&([az\d]{2,7}|#\d{2,5});/i", "\x05\x06$1", $string); $string = htmlspecialchars($string, ENT_QUOTES); $string = str_replace("\x05\x06", "&", $string); return $string; }
Это не идеально, но достаточно хорошо для моих нужд.