DomDocument — мощный инструмент работы с XML и HTML с использованием методов DOM. Главное при его использовании не запутаться в кодировках.

Конструктор DOMDocument принимает два параметра — версию и кодировку документа

$dom = new DOMDocument([ string $version [, string $encoding ]]);

А чтобы начать работать с существующим HTML-документом его надо загрузить в объект DOMDocument:

$dom->loadHTML( string $source );

Проблема в том, что документ загружается совсем не в той кодировке, что указана в конструкторе. Вообще, параметры конструктора никак не влияют на загруженный документ. А используются только при методах save():

$htmlString = $dom->saveHTML ();

Так что параметры конструктора можно совсем опустить, если вы собираетесь только работать с существующим деревом и не планируете его изменять и выгружать.

При загрузке же кодировка определяется только исходя из содержимого, загружаемого документа. При этом достаточно часто объект не может определить кодировку верно. Поэтому желательно указывать ее вручную. Возможны два способа. Добавить к импортируемому документу строку кодировки


$dom->loadHTML('<meta http-equiv="Content-Type" content="text/html; charset=utf-8">' . $source);

Либо сконвертировать все символы документа в HTML-entities перед импортом


$source = mb_convert_encoding($source, 'HTML-ENTITIES', 'utf-8');
$dom->loadHTML($source);

Первый вариант кажется предпочтительнее в плане производительности. В плане результатов работы различий замечено не было.

Если работать с DOM планируется много, то удобно оформить эти конструкции в отдельный класс наследника DOMDocument, добавить в методе загрузки дерева второй параметр кодировки и определить метод, например, так:


class MyDOMDocument extends DOMDocument {
    public function loadHTML($source, $encoding) {
        $source = '<meta http-equiv="Content-Type" content="text/html; charset='.
            $encoding.'">' . $source
        $dom->loadHTML('' . $source);
    }
}