Кодировки при работе с DOMDocument
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);
}
}