【发布时间】:2010-09-23 13:25:25
【问题描述】:
我们的目标是:用 & 替换所有独立的 & 符号。但不能替换那些已经属于 HTML 实体的部分,例如 。
我想我需要一个 PHP 正则表达式(最好是 preg_ 函数),它只匹配独立的 & 符号。我只是不知道如何使用 preg_replace 来做到这一点。
【问题讨论】:
我们的目标是:用 & 替换所有独立的 & 符号。但不能替换那些已经属于 HTML 实体的部分,例如 。
我想我需要一个 PHP 正则表达式(最好是 preg_ 函数),它只匹配独立的 & 符号。我只是不知道如何使用 preg_replace 来做到这一点。
【问题讨论】:
您总是可以在运行htmlentities 之前运行html_entity_decode?除非你只想做 & 符号(即使那样你也可以使用字符集参数)。
比正则表达式更容易和更快。
【讨论】:
Ross 让我得到了一个很好的答案。这是似乎运行良好的代码。迄今为止。 :-) 同样,目标是将 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');
【讨论】:
其他的都是很好的建议,可能是更好的方法。但我想我会尝试按要求回答这个问题——如果只是为了提供一个正则表达式示例。
以下是某些引擎中允许的特殊分解形式。当然,奇怪的是允许注释正则表达式的引擎允许其他简化表达式 - 但不是通用的。我会将这些简化的表达式放在 cmets 中的括号中。
& # 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 ';'
【讨论】:
PHP 的 htmlentities() 对此有 double_encode 参数。
如果你想在正则表达式中做类似的事情,那么否定断言会很有用:
preg_replace('/&(?!(?:[[:alpha:]][[:alnum:]]*|#(?:[[:digit:]]+|[Xx][[:xdigit:]]+));)/', '&', $txt);
【讨论】:
我也遇到了同样的问题,原来是用的:
$string = htmlspecialchars($string, ENT_QUOTES, "UTF-8", FALSE);
但需要它与 PHP4 和混合字符集一起使用,最终得到:
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;
}
它并不完美,但足以满足我的需求。
【讨论】: