Потому что при удалении атрибута происходит перенумерация остальных. Пусть есть три атрибута, их номера будут 0, 1 и 2.
Шаг 1.
$i = 0.
Удаляем атрибут 0.
Атрибуты 1 и 2 получают номера 0 и 1.
Шаг 2.
$i = 1.
Удаляем атрибут 1.
Остался атрибут 0.
Ну а PHP здесь совсем не виноват.
foreach ($this->allowableTags as $tag) {
foreach ($doc->getElementsByTagName($tag) as $element) {
$attributes = $element->attributes;
while ($attributes->length > 0) {
$attr = $attributes->item(0);
$this->clearElement($element, $attr);
}
}
}