You can get a list of all html entities and use this to replace all without semicolon by their UTF-8 representations:
// get all HTML entities
$mapping = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES | ENT_HTML5, 'UTF-8');
// change array values representing the entities to regex pattern with negativ lookahead for semicolon
array_walk($mapping, function(&$value) { $value = '/'.rtrim($value, ';').'(?!;)/'; });
// replace all entities without semicolon by their utf8 representation
$html = preg_replace(array_values($mapping), array_keys($mapping), $html);