2010-08-19 31 views
6

Tôi đang sử dụng DOMDocument để thao tác/sửa đổi HTML trước khi nó được xuất ra trang. Đây chỉ là một đoạn html, không phải là một trang hoàn chỉnh. Vấn đề ban đầu của tôi là tất cả các nhân vật Pháp đã bị rối tung lên, mà tôi đã có thể sửa chữa sau một số thử nghiệm và lỗi. Bây giờ, có vẻ như chỉ có một vấn đề vẫn còn: 'nhân vật được biến thành? .Các vấn đề/ký tự mã hóa DOMDocument được chuyển đổi

Mã:

<?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()))); 
?> 

Tôi biết nó đang trở nên lộn xộn với utf8 giải mã/mã hóa, nhưng đây là cách duy nhất tôi có thể làm cho nó hoạt động cho đến nay. Dưới đây là một chuỗi mẫu:

Input: Sans doute parce qu'il vient d'atteindre ngày une định thức dans son spectaculaire cheminement

Output:? Sans doute parce qu il vient d ngày atteindre une d & eacute ; terminante dans son spectaculaire cheminement

Nếu tôi tìm thấy thêm chi tiết, tôi sẽ thêm chúng. Cảm ơn bạn đã dành thời gian và hỗ trợ của bạn!

+1

Bộ ký tự nào là '$ row-> text'?Nếu nó là UTF-8 trực tiếp (Giả sử nó đến từ MySQL, bạn cần đặt bộ ký tự kết nối thành UTF8) thì bạn không cần hàm 'utf8_ (en | de) code'. Buộc bộ ký tự thành UTF8 và tất cả các vấn đề của bạn * nên * biến mất (giả sử đó là nơi '$ row' xuất phát) ... – ircmaxell

+0

Đầu vào đến từ CMS, tất cả được đặt thành utf8 (chuỗi, cơ sở dữ liệu, v.v.). Nhưng có vẻ như vấn đề của tôi không phải là điều tôi nghĩ. Tôi phát hiện ra rằng chuỗi đến từ tôi là tất cả OK, và đồng nghiệp của tôi 'pc quá. Vấn đề chỉ xảy ra khi chuỗi đang được đầu vào bởi máy tính của khách hàng của tôi. Tôi cá là cô ấy đang dán văn bản từ lời nói hay gì đó và một số thứ kỳ lạ đang diễn ra. Tôi sẽ phải digg vào này. – Kyrotomia

+1

Ahhh ... Sau đó, có lẽ kiểm tra các ký tự UCS-2LE (UTF-16LE) (Vì đó là mặc định cho Word IIRC) ... – ircmaxell

Trả lời

16

Không sử dụng utf8_decode. Nếu văn bản của bạn ở dạng UTF-8, hãy chuyển nó như vậy.

Thật không may, DOMDocument mặc định là LATIN1 trong trường hợp HTML. Có vẻ như hành vi này là này

  • Nếu lấy một tài liệu từ xa, nó nên suy ra mã hóa từ các tiêu đề
  • Nếu tiêu đề không được gửi hoặc các tập tin là địa phương, tìm kiếm các phóng viên meta-equiv
  • Nếu không, hãy mặc định là LATIN1.

Ví dụ về nó làm việc:

<?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; 

Và với XML (mặc định là 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

nếu tôi nhớ đúng, tôi nghĩ rằng tôi đã sử dụng để sửa lỗi sau để đảm bảo html được đặt thành utf8, '$ d-> loadHTML (''. $ html);' là nó luôn có vẻ phục hồi tốt khi phân tích cú pháp html không hợp lệ anyway – goat

+0

@chris Tôi đã từng làm điều đó, cho đến khi nó bị phá vỡ gần đây. Câu trả lời là chính xác, cần có thẻ để thẻ hoạt động trơn tru; xem thêm: https://bugs.php.net/bug.php?id=32547 –

+0

CÓ, CẢM ƠN! Đây là giải pháp: KHÔNG chuyển đổi mã UTF8 gốc của bạn, chỉ thêm thẻ META. PS: và có thể đơn giản hơn, tôi đã thử nghiệm mà không có thẻ gốc HTML, chỉ có thẻ P và bắt đầu với META này. –

7

loadHtml() không phải lúc nào nhận ra mã hóa đúng như quy định trong nội dung -loại thẻ meta HTTP-EQUIV.

Nếu DomDocument('1.0', 'UTF-8')loadHTML('<?xml version="1.0" encoding="UTF-8"?>' . $html) hacks không làm việc như họ đã làm không phải cho tôi (PHP 5.3.13), hãy thử này:

Thêm một phần <head> ngay sau thẻ mở <html> với đúng các trang nội dung nhập thẻ meta HTTP-EQUIV. Sau đó, gọi loadHtml(), sau đó xóa thêm <head> thẻ.

// 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> 

Xem bài viết này: http://devzone.zend.com/1538/php-dom-xml-extension-encoding-processing/

4

Đây là đủ đối với tôi, câu trả lời khác ở đây là quá mức cần thiết. Do tôi có một tài liệu HTML với một thẻ HEAD hiện có. Thẻ HEAD không có thuộc tính và tôi không có vấn đề nào để lại thẻ META phụ trong HTML cho trường hợp sử dụng của tôi.

$data = str_ireplace('<head>', '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />', $data); 
$document = new DOMDocument(); 
$document->loadHTML($data); 
Các vấn đề liên quan