[php] UTF-8을 올바르게 인코딩하지 않는 PHP DOMDocument loadHTML

DOMDocument를 사용하여 일부 HTML을 구문 분석하려고하지만 그렇게하면 갑자기 인코딩이 손실됩니다 (적어도 그것이 나에게 나타나는 방식입니다).

$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人が俳優になった。父親は木材のセールスマンで、母親は郵便局の客室係だった。高校時代はキャディのアルバイトに勤しみ、教育資金を受けながらカトリック系の高校へ進学

편집 : 코드를 5 줄로 단순화하여 직접 테스트 할 수 있습니다.

$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달리 명시하지 않는 한 문자열을 ISO-8859-1에있는 것으로 간주합니다. 이로 인해 UTF-8 문자열이 잘못 해석됩니다.

문자열에 XML 인코딩 선언이 포함되어 있지 않은 경우 문자열 앞에 UTF-8로 처리되도록 할 수 있습니다.

$profile = '<p>イリノイ州シカゴにて、アイルランド系の家庭に、9</p>';
$dom = new DOMDocument();
$dom->loadHTML('<?xml encoding="utf-8" ?>' . $profile);
echo $dom->saveHTML();

문자열에 이러한 선언이 이미 포함되어 있는지 알 수없는 경우 SmartDOMDocument에 다음 과 같은 해결 방법이 있습니다.

$profile = '<p>イリノイ州シカゴにて、アイルランド系の家庭に、9</p>';
$dom = new DOMDocument();
$dom->loadHTML(mb_convert_encoding($profile, 'HTML-ENTITIES', 'UTF-8'));
echo $dom->saveHTML();

이것은 훌륭한 해결 방법은 아니지만 모든 문자를 ISO-8859-1 (이 katana와 같이)로 표현할 수있는 것은 아니므로 가장 안전한 대안입니다.


답변

문제는 saveHTML()및에 saveXML()있으며 둘 다 Unix에서 올바르게 작동하지 않습니다. Unix에서 사용될 때 UTF-8 문자를 올바르게 저장하지 않지만 Windows에서는 작동합니다.

해결 방법은 매우 간단합니다.

기본값을 사용하면 설명 된 오류가 발생합니다.

$str = $dom->saveHTML(); // saves incorrectly

다음과 같이 저장하면됩니다.

$str = $dom->saveHTML($dom->documentElement); // saves correctly

이 코드 줄은 UTF-8 문자가 올바르게 저장되도록합니다. 를 사용하는 경우 동일한 해결 방법을 사용하십시오 saveXML().


최신 정보

아래의 댓글 섹션에서 ” Jack M “이 제안하고 ” Pamela “및 ” Marco Aurélio Deleu “가 확인한 경우 다음과 같은 변형이 작동 할 수 있습니다.

$str = utf8_decode($dom->saveHTML($dom->documentElement));

노트

  1. 영어 문자는 saveHTML()매개 변수없이 사용할 때 아무런 문제를 일으키지 않습니다 (영어 문자는 UTF-8에서 단일 바이트 문자로 저장되므로)

  2. 멀티 바이트 문자 (예 : 중국어, 러시아어, 아랍어, 히브리어 등)가있는 경우 문제가 발생합니다.

이 기사를 읽는 것이 좋습니다 : http://coding.smashingmagazine.com/2012/06/06/all-about-unicode-utf8-character-sets/ . UTF-8의 작동 방식과이 문제점이있는 이유를 이해합니다. 약 30 분이 소요되지만 시간이 많이 소요됩니다.


답변

실제 소스 파일이 UTF-8로 저장되어 있는지 확인하십시오 (권장하지 않는 BOM Chars를 UTF-8과 함께 사용해 볼 수도 있습니다).

또한 HTML의 경우 meta태그를 사용하여 올바른 인코딩을 선언했는지 확인하십시오 .

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

CMS 인 경우 (Jomla로 질문에 태그를 추가 한 것처럼) 인코딩에 적절한 설정을 구성해야 할 수 있습니다.


답변

다음 utf-8과 같이 인코딩을 적용하는 줄을 앞에 붙일 수 있습니다 .

@$doc->loadHTML('<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $profile);

그런 다음 다음과 같이 기존 코드를 계속 사용할 수 있습니다.

$doc->saveXML()


답변

이것은 알아내는 데 시간이 걸렸지 만 여기에 내 대답이 있습니다.

DomDocument를 사용하기 전에 file_get_contents를 사용하여 URL을 검색 한 다음 문자열 함수로 처리합니다. 아마도 가장 좋은 방법은 아니지만 빠를 것입니다. Dom이 빠르다고 확신 한 후 처음으로 다음을 시도했습니다.

$dom = new DomDocument('1.0', 'UTF-8');
if ($dom->loadHTMLFile($url) == false) { // read the url
    // error message
}
else {
    // process
}

적절한 메타 태그, PHP 설정 및 여기 및 다른 곳에서 제공되는 모든 구제책에도 불구하고 UTF-8 인코딩을 보존하는 데 크게 실패했습니다. 작동하는 내용은 다음과 같습니다.

$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에 HTML 버전을 제공해야합니다. HTML5처럼.

$profile ='<?xml version="1.0" encoding="'.$_encoding.'"?>'. $html;

어쩌면 당신이 문제에하지 않도록 당신이 주변에 … 쿼리를 시작합니다 때, 당신이 할 수있는 유효로 HTML을 유지 :-)하고 멀리하는 좋은 아이디어입니다 htmlentities!!!! 그것은 앞뒤로 필요한 자원 낭비입니다. 당신의 코드를 미쳐 버리세요 !!!!


답변

manjaro에서 PHP 7.3.8을 사용하고 있으며 페르시아어 콘텐츠로 작업하고있었습니다. 이것은 내 문제를 해결했다.

$html = 'hi</b><p>سلام<div>の家庭に、9 ☆';
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
print $doc->saveHTML($doc->documentElement) . PHP_EOL . PHP_EOL;