2010-06-29 30 views
9

Tôi đã sử dụng DOM của PHP để tải mẫu html, sửa đổi và xuất nó. Gần đây tôi phát hiện ra rằng các thẻ tự đóng (trống) không bao gồm dấu gạch chéo, mặc dù tệp mẫu đã làm.Tại sao PHP DOM không bao gồm dấu gạch chéo trên các thẻ tự đóng?

ví dụ:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"`"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 
</head> 
<body> 
</body> 
</html> 

trở thành:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
</head> 
<body> 
</body> 
</html> 

Đây có phải là một lỗi hoặc một thiết lập, hoặc một vấn đề DOCTYPE?

+0

Bạn đã thử thêm một loại tài liệu để xem điều gì sẽ xảy ra? – ceejayoz

+0

Tôi đã luôn sử dụng một loại tài liệu XHTML, nghĩ rằng nó không liên quan vì tôi mệt mỏi -_- – peterjwest

Trả lời

19

DOMDocument->saveHTML() lấy tập dữ liệu XML DOM của bạn và viết nó ra dưới dạng HTML cũ, chứ không phải XML. Bạn không nên sử dụng saveHTML() cùng với một loại tài liệu XHTML, vì đầu ra của nó sẽ không được định dạng đúng XML.

Nếu bạn sử dụng saveXML() thay vào đó, bạn sẽ nhận được XHTML thích hợp. Bạn có thể phân phối đầu ra XML này cho các trình duyệt tuân thủ tiêu chuẩn nếu bạn cung cấp cho nó tiêu đề Content-Type: application/xhtml+xml. Nhưng tiếc là IE6-8 sẽ không thể đọc được điều đó, vì chúng vẫn có thể xử lý HTML cũ, dưới loại phương tiện truyền thông text/html.

Giải pháp thỏa hiệp thông thường là phân phối text/html và sử dụng ‘XHTML tương thích HTML’ như được nêu trong Phụ lục C của thông số XHTML 1.0. Nhưng thật đáng buồn là không có phương thức PHP DOMDocument->saveXHTML() nào để tạo ra kết quả chính xác cho việc này.

Có một số điều bạn có thể làm để thuyết phục saveXML() để tạo đầu ra tương thích HTML cho một số trường hợp phổ biến. Điều quan trọng nhất là bạn phải đảm bảo rằng chỉ các phần tử được xác định bởi HTML4 là có một mô hình nội dung EMPTY (<img>, <br> v.v.) thực sự có nội dung trống, khiến cú pháp tự đóng (<img/>) được sử dụng. Các yếu tố khác không được sử dụng cú pháp tự đóng, vì vậy nếu chúng trống, bạn nên đặt một khoảng trống trong nội dung văn bản của chúng để ngăn chúng như vậy:

<script src="x.js"/>   <-- no good, confuses HTML parser and breaks page 
<script src="x.js"> </script> <-- fine 

Cách khác để tìm hiểu là xử lý nội tuyến <script><style> yếu tố, là các phần tử bình thường trong XHTML nhưng đặc biệt là các phần tử nội dung CDATA trong HTML. Cần có một số gói /*<![CDATA[*/.../*]]>*/ để thực hiện bất kỳ ký tự nào < hoặc & bên trong chúng hoạt động chủ yếu nhất quán, mặc dù lưu ý rằng bạn vẫn phải tránh các chuỗi ]]></.

Nếu bạn muốn thực sự làm đúng cách, bạn sẽ phải viết trình tuần tự XHTML tương thích HTML của riêng mình. Dài hạn có lẽ sẽ là một lựa chọn tốt hơn. Nhưng đối với các trường hợp đơn giản nhỏ, lấy cắp dữ liệu đầu vào của bạn để nó không chứa bất kỳ thứ gì có thể xuất hiện ở đầu kia của trình tuần tự XML không tương thích với HTML có lẽ là giải pháp nhanh.

Điều đó hoặc chỉ hút nó lên và sống với trường học cũ không phải là XML HTML, rõ ràng.

+0

Cảm ơn bạn đã trả lời chi tiết. Tôi đã luôn luôn ghét DOM của PHP, tuy nhiên đây là đóng băng trên quan tài. Tôi có thể thử một số xử lý trước/sau regex đơn giản để thay đổi đầu vào/đầu ra bằng saveXML(). Đây không phải là một giải pháp lý tưởng. DOM của PHP có hỗ trợ HTML 5 không? – peterjwest

+0

Tránh đầu ra mã hóa regex-hacking HTML bằng mọi giá. (Nhưng tôi sẽ nói rằng, phải không?) Viết một serialiser XHTML không phải là xấu (XML là cách dễ dàng hơn để serialize hơn là phân tích cú pháp); nó sẽ chậm, nhưng sau đó chuẩn bị các mẫu với 'DOMDocument' khá chậm nói chung. Đối với HTML5, nó sẽ hoạt động hiệu quả giống như HTML4. PHP không biết về các phần tử HTML5 mới, vì vậy nếu bạn sử dụng bất kỳ phần tử nào phải là 'EMPTY' (ví dụ: ''), bạn sẽ nhận được thẻ kết thúc không hợp lệ cho chúng. – bobince

+0

Oh wow, [bạn sẽ] (http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454) nói điều đó. Bạn có biết cách chuẩn bị nhanh các mẫu (HTML hoặc XHTML) trong PHP không? – peterjwest

2

vấn đề DOCTYPE vì nó là text/html đóng dấu gạch chéo là không cần thiết, bạn chỉ cần slash đóng cửa nếu nó là một doc xhtml

ghi nhận bạn đã cập nhật thêm trong DOCTYPE, nhưng PHP dom cũng có vẻ tại thẻ meta bạn đã có trong đó và nội dung = "text/html; charset = utf-8" rõ ràng không phải là XML, nó chỉ là văn bản/html :)

sang một bên: DOM api cũng chọn bộ ký tự từ đó

+1

tôi vẫn không hiểu tại sao mọi người sử dụng docxpe xhtml - đặc biệt là khi họ sử dụng kiểu nội dung của văn bản/html làm cho trang web của họ hoạt động bình thường trong IE ... cho 99% web, xhtml không cung cấp bất kỳ lợi thế nào cho HTML4.01 với chi phí phải triển khai không đúng cách (viz. content-type = text/html) – HorusKol

+0

xhtml là chuỗi công cụ XML tương thích và có đầu tư rất lớn vào công cụ XML, có thể không tạo sự khác biệt cho trình duyệt, nhưng chắc chắn tạo sự khác biệt cho nhiều khách hàng và máy phát khác (đặc biệt là nếu bạn thêm xslt v.v. vào trộn) – nathan

-1

Đây là một câu hỏi cũ, nhưng ...
Như của khác đã nêu, PHP DOM nhiều lá để được mong muốn ...
Dưới đây là một regex để đóng "khoảng trống" thẻ nếu bạn rất mong muốn

$voidTags = array('area','base','br','col','command','embed','hr','img','input','keygen','link','meta','param','source','track','wbr'); 
$regEx = '#<('.implode('|', $voidTags).')(\b[^>]*)>#'; 
$html = preg_replace($regEx, '<\\1\\2 />', $html); 
+0

Dường như có một số vấn đề. Tôi sửa đổi nó và điều này làm việc cho tôi: '$ regEx = '# <\ b ('. Implode ('|', $ voidTags). ') ([^>] +)><\/\b\1> #g';' – user594044

Các vấn đề liên quan