Я могу использовать str_replace для кодирования всех &, но если я делаю это с <или>, я делаю это и для допустимых тегов XML.
В качестве строго временной меры исправления вы можете заменить те, которые не являются частью того, что выглядит как ссылка на тег или сущность, например ::
$str= preg_replace('<(?![a-zA-Z_!?])', '<', $str);
$str= preg_replace('&(?!([a-zA-Z]+|#[0-9]+|#x[0-9a-fA-F]+);)', '&', $str);
Однако это не является водонепроницаемым, и в долгосрочной перспективе вам нужно исправить то, что генерирует эту фиктивную разметку, или кричать на человека, который должен это исправить, пока он не получит подсказку. Совсем не правильно сформированный XML, подобный этому, просто не XML по определению.