2010-08-19 67 views
6

我使用DOMDocument操縱/修改HTML之前,它獲得輸出到頁面。這只是一個html片段,而不是一個完整的頁面。我最初的問題是,所有的法國人物都搞砸了,經過一番反覆試驗後,我能夠糾正。現在,似乎只有一個問題仍然存在:「角色變成了? 。DOMDocument編碼問題/字符轉換

代碼:

<?php 
    $dom = new DOMDocument('1.0','utf-8'); 
     $dom->loadHTML(utf8_decode($row->text)); 

     //Some pretty basic modification here, not even related to text 

     //reinsert HTML, and make sure to remove DOCTYPE, html and body that get added auto. 
     $row->text = utf8_encode(preg_replace('/^<!DOCTYPE.+?>/', '', str_replace(array('<html>', '</html>', '<body>', '</body>'), array('', '', '', ''), $dom->saveHTML()))); 
?> 

我知道它變得凌亂與UTF8解碼/編碼,但這是我可以使它工作至今的唯一途徑。下面是一個簡單的字符串:

輸入: 三世doute parce qu'il vient D'atteindre UNE日期行列式丹斯兒子spectaculaire cheminement

輸出:?? 三世doute parce曲IL vient d atteindre UNE日期d&eac​​ute ;如果我找到更多的細節,我會添加它們。感謝您的時間和支持!

+1

什麼字符集是'$ row-> text'?如果它是直接使用UTF-8(假設它來自MySQL,則需要將連接字符集設置爲UTF8),那麼您不需要'utf8_(en | de)代碼函數。強制將字符集轉換爲UTF8,並且所有問題*應該消失(假設這是'$ row'的來源)... – ircmaxell 2010-08-19 15:35:16

+0

輸入來自CMS,全部設置爲utf8(字符串,數據庫等等)。 但似乎我的問題不是我認爲的那樣。我發現從我身上傳來的字符串都沒問題,還有我的同事的電腦。只有當我的客戶端電腦輸入字符串時纔會出現問題。我敢打賭,她正在從文字或其他任何東西上粘貼文本,然後發生一些奇怪的事情。我將不得不深究這一點。 – Kyrotomia 2010-08-19 15:43:31

+1

Ahhh ...然後可能檢查UCS-2LE(UTF-16LE)字符(因爲這是Word IIRC的默認設置)... – ircmaxell 2010-08-19 15:45:23

回答

16

請勿使用utf8_decode。如果您的文本使用UTF-8,請將其傳遞。

不幸的是,在HTML中,DOMDocument默認爲LATIN1。看來行爲是該

  • 如果獲取遠程的文件,它應該推斷從報頭中的編碼
  • 如果沒有發送的頭或文件是本地文件,查找對應的元當量
  • 否則,默認爲LATIN1。工作的它

實施例:

<?php 
$s = <<<HTML 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
</head> 
<body> 
Sans doute parce qu’il vient d’atteindre une date déterminante 
dans son spectaculaire cheminement 
</body> 
</html> 
HTML; 

libxml_use_internal_errors(true); 
$d = new domdocument; 
$d->loadHTML($s); 

echo $d->textContent; 

並與XML(默認爲UTF-8):

<?php 
$s = '<x>Sans doute parce qu’il vient d’atteindre une date déterminante'. 
    'dans son spectaculaire cheminement</x>'; 
libxml_use_internal_errors(true); 
$d = new domdocument; 
$d->loadXML($s); 

echo $d->textContent; 
+5

如果我沒有記錯的話我想我會用下面的hacky修復程序來確保html被設置爲utf8,'$ d-> loadHTML('<?xml version =「1.0」encoding =「UTF-8」?>'。$ html);'因爲它在解析無效html時似乎總能恢復得很好無論如何 – goat 2012-04-29 15:00:48

+0

@chris我曾經這樣做,直到最近破產。答案是正確的,它需要標籤才能順利運行;另見:https://bugs.php.net/bug.php?id=32547 – 2012-05-14 08:25:17

+0

是的,謝謝!這是解決方案:不轉換您的原始UTF8 HTML,只添加標籤META。 PS:並且可以更簡單,我沒有HTML根標籤進行測試,僅標記P並以此META開頭。 – 2013-02-25 14:15:21

7

loadHtml()並不總是識別正確的編碼作爲指定內容類型的HTTP-EQUIV元標記。

如果他們沒有爲我(PHP 5.3.13)的DomDocument('1.0', 'UTF-8')loadHTML('<?xml version="1.0" encoding="UTF-8"?>' . $html)黑客不工作,試試這個:

添加另一個<head>部分用正確的內容 - 開放<html>標籤後立即鍵入HTTP-EQUIV元標記。然後撥打loadHtml(),然後刪除多餘的<head>標籤。

// Ensure entire page is encoded in UTF-8 
$encoding = mb_detect_encoding($body); 
$body = $encoding ? @iconv($encoding, 'UTF-8', $body) : $body; 

// Insert a head and meta tag immediately after the opening <html> to force UTF-8 encoding 
$insertPoint = false; 
if (preg_match("/<html.*?>/is", $body, $matches, PREG_OFFSET_CAPTURE)) { 
    $insertPoint = mb_strlen($matches[0][0]) + $matches[0][1]; 
} 
if ($insertPoint) { 
    $body = mb_substr(
     $body, 
     0, 
     $insertPoint 
    ) . "<head><meta http-equiv='Content-type' content='text/html; charset=UTF-8' /></head>" . mb_substr(
     $body, 
     $insertPoint 
    ); 
} 
$dom = new DOMDocument(); 

// Suppress warnings for loading non-standard html pages 
libxml_use_internal_errors(true); 
$dom->loadHTML($body); 
libxml_use_internal_errors(false); 

// Now remove extra <head> 

看到這篇文章:http://devzone.zend.com/1538/php-dom-xml-extension-encoding-processing/

4

這是足以讓我,其他的答案這裏是矯枉過正。鑑於我有一個帶有現有HEAD標籤的HTML文檔。 HEAD標籤沒有屬性,我沒有任何問題在HTML中爲我的用例留下額外的META標籤。

$data = str_ireplace('<head>', '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />', $data); 
$document = new DOMDocument(); 
$document->loadHTML($data);