Jul 20

На этот пост меня сподвигла неправильная (на мой взгляд работа fillin-фильтра в Symfony). Итак, поехали.

DOM - это мощный компонент PHP для работы с Document Object Model. Почитать о его возможностях можно здесь (php manual). Я же хочу заострить внимание на том, что это расширение, в отличии от SimpleXML, например, может работать как с HTML, так и с XML.

DomDocument - один из классов компонента DOM, который отвечает за полный XML или HTML-документ.

И вот хотелось бы поговорить и показать, как этот DomDocument работает с кодировками и символами, отличными от латиницы.

Для начала - небольшое отступление: DomDocument я создаю вот так: new DomDocument('1.0', 'UTF-8'), указывая в качестве кодировки (”The encoding of the document as part of the XML declaration.”) UTF-8, так как, судя по моему опыту - указание кодировки здесь не дает вообще ничего.

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

Весь текст в скриптах в кодировке UTF-8.

Код класса “тестов”

class Test_DomDocument_HTML_Charset {
  protected $dom;

  protected $html =
        '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
        <html>
        <head>
          <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
          <title>Тестовая страничка</title>
        </head>
        <body>
          <p>Привет</p>
        </body>
        </html>';

  protected $html_without_charset =
        '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
        <html>
        <head>
          <title>Тестовая страничка</title>
        </head>
        <body>
          <p>Привет</p>
        </body>
        </html>';

  protected function checkTestFunction($function)
  {
    return (strpos($function, 'test') === 0);
  }

  public function execute($callback) {
    $functions = get_class_methods(get_class($this));
    $functions = array_filter($functions, array($this, 'checkTestFunction'));
    foreach($functions as $function) {
      $this->setUp();
      $result = $this->$function();
      $callback($result, $function);
      $this->tearDown();
    }
  }

  protected function setUp() {
    $this->dom = new DomDocument('1.0', 'UTF-8');
  }

  protected function tearDown() {
  }

  /**
   * Возвращает кодировку документа.
   * Используется документ, в котором не указана кодировка.
   *
   * @return string
   */
  protected function testWithoutCharset() {
    $this->dom->loadHTML($this->html_without_charset);
    return $this->dom->encoding;
  }

  /**
   * Возвращает документ, после обработки его DomDocument'ом.
   * Используется документ, в котором не указана кодировка.
   *
   * @return string
   */
  protected function testWithoutCharsetHtml() {
    $this->dom->loadHTML($this->html_without_charset);
    return $this->dom->saveHTML();
  }

  /**
   * Возвращает кодировку документа.
   * Используется документ, в котором указана кодировка.
   *
   * @return string
   */
  protected function testWithCharset() {
    $this->dom->loadHTML($this->html);
    return $this->dom->encoding;
  }

  /**
   * Возвращает документ, после обработки его DomDocument'ом.
   * Используется документ, в котором указана кодировка.
   *
   * @return string
   */
  protected function testWithCharsetHtml() {
    $this->dom->loadHTML($this->html);
    return $this->dom->saveHTML();
  }

}

Код, показывающий результаты

function echoHTMLResult($result, $function)
{
  echo "<h3>$function</h3>\n";
  echo '<pre><code>';
  if(is_string($result))
    $result = str_replace('<', '&lt;', str_replace('>', '&gt;', $result));
  var_dump($result);
  echo '</code></pre>';
}
<?php $test = new Test_DomDocument_HTML_Charset(); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
  <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
  <title>Тестовая страничка</title>
</head>
<body>
<?php $test->execute('echoHTMLResult') ?>
</body>
</html>

Результаты

Выводы

Как можно понять из результатов - кодировка документа при использовании HTML определяется исключительно через тег meta, а точнее - через charset, который там указан:

<meta http-equiv="Content-type" content="text/html; charset=UTF-8">

При отсутствии указанного тега/charset’а в нём - $dom->encoding будет равен NULL (что можно с успехом использовать).

В общем-то всё, в ближайшие дни еще будет статья про кодировку в XML-документах, где всё немного интереснее.

written by fxposter \\ tags: , , ,

One Ping to “DomDocument – кодировка в HTML-документах”

  1. DOMDocument::loadXML - кодировка UTF-8 для XML | Журнал веб разработчика Says:

    […] по теме: • DOMDocument::__construct • DOMDocument::loadXML • DomDocument – кодировка в HTML-документах Похожие статьи: Методы сортировки на php от Gustav […]


3 Responses to “DomDocument – кодировка в HTML-документах”

  1. 1. Stark Says:

    Попробуй создавать объект так:

    new DomDocument(‘1.0’, ‘utf8’)

  2. 2. Devis Says:

    А еще можно попробовать через “абракадабра” )))

  3. 3. Jujulka Says:

    Господин Hinikato подкинул несколько идей по изврату:)
    http://hinikato.blogspot.com/2008/10/php-xml.html

    причем тег нужно добавлять в самое начало

    @$domDoc->loadHTML('<meta http-equiv="content-type" content="text/html; charset=utf-8">' . $html);

    , а не как бы потребовал валидный хтмл (вовнутрь <head>)

Leave a Reply