7

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

7 комментариев

  • Sergey
    Март 3, 2013 at 1:16 пп

    Вы мой спаситель! Думал уже отказаться от идеи использования DOMDocument, как только я не пробовал обуздать кодировку выходного документа — а тут вот оно что…

  • Vladimir
    Март 30, 2014 at 5:02 пп

    $doc = new DOMDocument();
    $doc->substituteEntities = false; // loadHTML($content);
    $doc->saveHTML();

  • Май 19, 2015 at 1:51 пп

    Спасибо!
    Действительно так удобнее всего побороть кодировку.

  • fake
    Май 22, 2015 at 2:21 пп

    Люто плюсую! Спасибо Вам огромное!

  • Катерина
    Октябрь 14, 2015 at 1:57 пп
    
    class MyDOMDocument extends DOMDocument
    {
        public function loadHTML($source, $encoding = "UTF-8")
        {
            $source = '' . $source;
            parent::loadHTML($source);
        }
        public function loadXML($source, $encoding = "UTF-8")
        {
            $source = '' . $source;
            parent::loadXML($source);
        }
    }
    
  • Август 18, 2016 at 7:29 дп

    Мне тоже очень помогло. Спасибо!

  • Октябрь 15, 2017 at 11:05 дп

    на локальном сервере все работало отлично, загрузил на веб — кракозябры. помог ваш совет $dom->loadHTML(» . $source);

Leave a Reply

Copyright © 2017 — dec5e | Site design by Trevor Fitzgerald