What If By "Remove HTML Special Chars" You Meant "Replace Appropriately"?
After all, just look at your example...
& ©
If you're stripping this for an RSS feed, shouldn't you want the equivalents?
" ", &, ©
Or maybe you don't exactly want the equivalents. Maybe you'd want to have
just be ignored (to prevent too much space), but then have ©
actually get replaced. Let's work out a solution that solves anyone's version of this problem...
How to SELECTIVELY-REPLACE HTML Special Chars
The logic is simple: preg_match_all('/(&#[0-9]+;)/'
grabs all of the matches, and then we simply build a list of matchables and replaceables, such as str_replace([searchlist], [replacelist], $term)
. Before we do this, we also need to convert named entities to their numeric counterparts, i.e., " "
is unacceptable, but "�A0;"
is fine. (Thanks to it-alien's solution to this part of the problem.)
Working Demo
In this demo, I replace {
with "HTML Entity #123"
. Of course, you can fine-tune this to any kind of find-replace you want for your case.
Why did I make this? I use it with generating Rich Text Format from UTF8-character-encoded HTML.
See full working demo:
Full Online Working Demo
function FixUTF8($args) {
$output = $args['input'];
$output = convertNamedHTMLEntitiesToNumeric(['input'=>$output]);
preg_match_all('/(&#[0-9]+;)/', $output, $matches, PREG_OFFSET_CAPTURE);
$full_matches = $matches[0];
$found = [];
$search = [];
$replace = [];
for($i = 0; $i < count($full_matches); $i++) {
$match = $full_matches[$i];
$word = $match[0];
if(!$found[$word]) {
$found[$word] = TRUE;
$search[] = $word;
$replacement = str_replace(['&#', ';'], ['HTML Entity #', ''], $word);
$replace[] = $replacement;
}
}
$new_output = str_replace($search, $replace, $output);
return $new_output;
}
function convertNamedHTMLEntitiesToNumeric($args) {
$input = $args['input'];
return preg_replace_callback("/(&[a-zA-Z][a-zA-Z0-9]*;)/",function($m){
$c = html_entity_decode($m[0],ENT_HTML5,"UTF-8");
# return htmlentities($c,ENT_XML1,"UTF-8"); -- see update below
$convmap = array(0x80, 0xffff, 0, 0xffff);
return mb_encode_numericentity($c, $convmap, 'UTF-8');
}, $input);
}
print(FixUTF8(['input'=>"Oggi è un bel giorno"]));
Input:
"Oggi è un bel giorno"
Output:
Oggi HTML Entity #232 un belHTML Entity #160giorno