Я пытаюсь разобрать HTML-код с использованием DOMDocument, но когда я это делаю, я внезапно теряю свою кодировку (по крайней мере, так мне кажется).
$profile = "<div><p>various japanese characters</p></div>"; $dom = new DOMDocument(); $dom->loadHTML($profile); $divs = $dom->getElementsByTagName('div'); foreach ($divs as $div) { echo $dom->saveHTML($div); }
Результатом этого кода является то, что я получаю кучу символов, которые не являются японцами. Однако, если я это сделаю:
echo $profile;
он отображается правильно. Я попробовал saveHTML и saveXML, и ни один из них не отображается правильно. Я использую PHP 5.3.
Что я вижу:
ã¤ãªãã¤å·ã·ã«ã´ã«ã¦ãã¢ã¤ã«ã©ã³ãç³»ã®å®¶åºã«ã9人åå¼ã®5çªç®ã¨ãã¦çã¾ãããå½¼ãå«ãã¦4人ã俳åªã«ãªã£ããç¶è¦ªã¯æ¨æã®ã»ã¼ã«ã¹ãã³ã§ãæ¯è¦ªã¯éµä¾¿å±ã®å®¢å®¤ä¿ã ã£ããé«æ ¡æ代ã¯ãã£ãã£ã®ã¢ã«ãã¤ãã«å¤ãã¿ãæè²è³éãåããªããã«ããªãã¯ç³»ã®é«æ ¡ã¸é²å¦ã
Что следует показать:
イリノイ州シカゴにて、アイルランド系の家庭に、9人兄弟の5番目として生まれる。彼を含めて4人が俳優になった。父親は木材のセールスマンで、母親は郵便局の客室係だった。高校時代はキャディのアルバイトに勤しみ、教育資金を受けながらカトリック系の高校へ進学
EDIT: я упростил код до пяти строк, чтобы вы могли проверить его самостоятельно.
$profile = "<div lang=ja><p>イリノイ州シカゴにて、アイルランド系の家庭に、</p></div>"; $dom = new DOMDocument(); $dom->loadHTML($profile); echo $dom->saveHTML(); echo $profile;
Вот html, который возвращается:
<div lang="ja"><p>イリノイ州シカゴã«ã¦ã€ã‚¢ã‚¤ãƒ«ãƒ©ãƒ³ãƒ‰ç³»ã®å®¶åºã«ã€</p></div> <div lang="ja"><p>イリノイ州シカゴにて、アイルランド系の家庭に、</p></div>
DOMDocument::loadHTML
будет обрабатывать вашу строку как DOMDocument::loadHTML
в ISO-8859-1, если вы не сообщите об этом иначе. Это приводит к тому, что строки UTF-8 интерпретируются неправильно. В SmartDOMDocument есть обходное решение, которое должно помочь вам:
$profile = '<div><p>イリノイ州シカゴにて、アイルランド系の家庭に、9</p></div>'; $dom = new DOMDocument(); $dom->loadHTML(mb_convert_encoding($profile, 'HTML-ENTITIES', 'UTF-8')); echo $dom->saveHTML($dom->getElementsByTagName('div')->item(0));
Альтернативой является добавление HTML с объявлением кодировки XML для обработки строки как UTF-8 при условии, что документ еще не содержит один:
$dom->loadHTML('<?xml encoding="utf-8" ?>' . $profile);
Проблема заключается в saveHTML()
и saveXML()
, оба из них не работают корректно в Unix. Они не сохраняют символы UTF-8 правильно, если они используются в Unix, но они работают в Windows.
Обходной путь очень прост:
Если вы попробуете значение по умолчанию, вы получите сообщение об ошибке
$str = $dom->saveHTML(); // saves incorrectly
Все, что вам нужно сделать, это сохранить следующее:
$str = $dom->saveHTML($dom->documentElement); // saves correctly
Эта строка кода позволит правильно сохранить ваши символы UTF-8 (используйте тот же обходной путь, если вы используете saveXML()
).
Английские символы не вызывают никаких проблем при использовании saveHTML()
без параметров (поскольку английские символы сохраняются как одиночные байтовые символы в UTF-8)
Проблема возникает, когда у вас многобайтовые символы (например, китайский, русский, арабский, иврит и т. Д.).
Я рекомендую прочитать эту статью: http://coding.smashingmagazine.com/2012/06/06/all-about-unicode-utf8-character-sets/ . Вы поймете, как работает UTF-8 и почему у вас есть эта проблема. Это займет у вас около 30 минут, но это время хорошо проведено.
Убедитесь, что реальный исходный файл сохранен как UTF-8 (возможно, вы даже захотите попробовать не рекомендованные маркеры спецификации с UTF-8, чтобы убедиться).
Также в случае HTML убедитесь, что вы указали правильную кодировку, используя meta
:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Если это CMS (как вы отметили свой вопрос с помощью Joomla), вам может потребоваться настроить соответствующие настройки для кодирования.
Вы можете префикс строки, обеспечивающей кодировку utf-8
, например:
@$doc->loadHTML('<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $profile);
И вы можете продолжить с кодом, который у вас уже есть, например:
$doc->saveXML()
Вы должны подать DOMDocument версию вашего HTML с заголовком, который имеет смысл. Также как HTML5.
$profile ='<?xml version="1.0" encoding="'.$_encoding.'"?>'. $html;
возможно, это хорошая идея, чтобы ваш html был как можно более действенным, так что вы не попадаете в проблемы, когда вы начнете запрос … вокруг 🙂 и избегайте htmlentities
!!!! Это необходимый ресурс назад и вперед. держите свой код безумным !!!!
Работы находят для меня:
$dom = new \DOMDocument; $dom->loadHTML(utf8_decode($html)); ... return utf8_encode( $dom->saveHTML());
Мне потребовалось некоторое время, чтобы разобраться, но вот мой ответ.
Перед использованием DomDocument я бы использовал file_get_contents для извлечения URL-адресов, а затем обработал их строковыми функциями. Возможно, это не лучший способ, но быстрый. Убедившись, что Дом был таким же быстрым, я сначала попробовал следующее:
$dom = new DomDocument('1.0', 'UTF-8'); if ($dom->loadHTMLFile($url) == false) { // read the url // error message } else { // process }
Это не удавалось эффектно сохранить кодировку UTF-8, несмотря на правильные метатеги, настройки php и все остальные средства, предлагаемые здесь и в других местах. Вот что работает:
$dom = new DomDocument('1.0', 'UTF-8'); $str = file_get_contents($url); if ($dom->loadHTML(mb_convert_encoding($str, 'HTML-ENTITIES', 'UTF-8')) == false) { }
и т. д. Теперь все в порядке с миром. Надеюсь это поможет.
Проблема заключается в том, что при добавлении параметра в функцию DOMDocument :: saveHTML () вы теряете кодировку. В некоторых случаях вам нужно избегать использования параметра и использовать функцию старой строки, чтобы найти то, что вы ищете.
Я думаю, что предыдущий ответ работает на вас, но поскольку это обходное решение не сработало для меня, я добавляю этот ответ, чтобы помочь ppl, который может быть в моем случае.
Используйте его для правильного результата
$dom = new DOMDocument(); $dom->loadHTML('<meta http-equiv="Content-Type" content="text/html; charset=utf-8">' . $profile); echo $dom->saveHTML(); echo $profile;
Эта операция
mb_convert_encoding($profile, 'HTML-ENTITIES', 'UTF-8');
Это плохо, потому что специальные символы, , & gt; может быть в $ profile, и они не будут конвертировать два раза после mb_convert_encoding. Это отверстие для XSS и неправильный HTML.
Попробуйте использовать utf8_encode