PHP: Xử Lý Source HTML Sử Dụng DOMDocument
Trên môi trường browser, sử dụng JavaScript chúng ta có thể thực hiện các thao tác với trang văn bản HTML như tìm các phần tử với các tag name (tên thẻ) cho trước, tìm các phần tử với ID hoặc Class cho trước, lấy ra nội dung phần tử hoặc chỉnh sửa nội dung này, xóa phần tử, thêm phần tử... Ví dụ ...
Trên môi trường browser, sử dụng JavaScript chúng ta có thể thực hiện các thao tác với trang văn bản HTML như tìm các phần tử với các tag name (tên thẻ) cho trước, tìm các phần tử với ID hoặc Class cho trước, lấy ra nội dung phần tử hoặc chỉnh sửa nội dung này, xóa phần tử, thêm phần tử...
Ví dụ như nếu cần tìm kiếm danh sách các phần tử a hoặc img thì sử dụng thư viện jQuery trong JavaScript chúng ta có thể thực hiện công đoạn này như sau:
$aElements = $('a'); $imgElements = $('img');
Và nếu muốn thêm thuộc tính rel="nofollow" cho các phần tử a:
$('a').attr("rel", "nofollow");
Trong không ít các trường hợp thì bạn muốn công việc sửa đổi mã HTML được thực hiện trên server thay vì dưới client. Nếu sử dụng PHP là ngôn ngữ lập trình server thì bạn có thể thực hiện các thao tác trên sử dụng thư viện DOMDocument. Trong bài viết này chúng ta sẽ tìm hiểu các sử dụng DOMDocument để thực hiện các tác vụ với văn bản HTML.
Để làm theo hướng dẫn của bài học bạn hãy tạo một file post_content.txt với nội dung như sau:
<h1>Sample post title</h1> <a href="/link-1">Link 1</a> <a href="/link-2">Link 2</a>
Tiếp theo tạo một file post.php ở cùng thư mục chứa file post_content.txt với nội dung như sau:
<?php $html = file_get_contents('post_content.txt'); echo $html; ?>
Bây giờ nếu sử dụng trình duyệt và truy cập vào trang post.php và view source của trang bạn sẽ thấy nội dung như sau:
<html> <head> <meta charset="utf-8"> </head> <body> <h1>Sample post title</h1> <a href="/link-1">Link 1</a> <a href="/link-2">Link 2</a> </body> </html>
Tới đây bạn đã sẵn sàng để bắt đầu viết thêm code PHP xử lý mã HTML có trong tập tin post_content.txt. Chúng ta sẽ làm điều đó ở phần tiếp theo đây.
Khởi Tạo Object DOMDocument
PHP cung cấp class DOMDocument cho phép chúng ta có thể thực hiện các thao tác với Document Object Model của trang HTML. Trong file post.php bạn sửa đổi đoạn code PHP để thực hiện việc khởi tạo object từ class DOMDocument như sau:
<?php $html = file_get_contents('post_content.txt'); $doc = new DOMDocument(); $doc->loadHTML($html); echo $doc->saveHTML(); ?>
Trong đoạn code trên, sau khi khởi tạo object của class DOMDOCUMENT thì sau đó chúng ta còn gọi hai method:
- loadHTML(): Method này sẽ thực hiện việc load HTML từ source, nghĩa là đối số truyền vào method sẽ có kiểu dữ liệu là String.
- saveHTML(): Method này sẽ trả về source HTML sau khi được xử lý. Do chúng ta chưa thực hiện việc xử lý mã HTML được truyền vào ban đầu nên kết quả hiển thị vẫn không có gì thay đổi.
Ngoài ra, khi khởi tạo object từ class DOMDocument trong PHP chúng ta cũng có thể load trực tiếp từ file HTML:
<?php $doc = new DOMDocument(); $doc->loadHTMLFile('post_content.txt'); echo $doc->saveHTML(); ?>
Bạn có thể chọn 1 trong hai cách load HTML sau khi khởi tạo object. Sau đó nếu dùng trình duyệt để truy cập trang ứng với file post.php trên server bạn sẽ thấy kết quả như sau:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> <html><body><h1>Sample post title</h1> <a href="/link-1">Link 1</a> <a href="/link-2">Link 2</a></body></html>
Bạn có thể thấy khi gọi $doc->saveHTML(), PHP tự động nén mã HTML lại đồng thời thêm khai báo DOCTYPE và các thẻ <html> và <body> ở bên ngoài nội dung của bài viết cho chúng ta.
Chọn Phần Tử
Để chọn ra các phần tử với tên tag name cho trước, chúng ta sử dụng method getElementsByTagName() của DOMDocument:
<?php $html = file_get_contents('post_content.txt'); $doc = new DOMDocument(); $doc->loadHTML($html); // Chọn ra các phần tử a $aElements = $document->getElementsByTagName('a'); foreach ($aElements as $aElement) { // lặp qua các phần tử // ... } // Hiển thị mã HTML echo $doc->saveHTML(); ?>
Ở trên giá trị trả về sau khi gọi method getElementsByTagName() được lưu trong biến $aElements, biến này là một object của class DOMNodeList chứa danh sách các phần tử a (hay Node a) trong văn bản HTML. Chúng ta sau đó sử dụng vòng lặp foreach để lặp qua danh sách các phần tử trả về. Mỗi một key trong vòng lặp foreach (biến $aElement) là một Node. Biến $aElement là một object của class DOMNode.
Lấy Giá Trị Thuộc Tính Của Phần Tử
Tiếp theo chúng ta gọi method getAttribute() để lấy về giá trị một attribute của phần tử:
<?php $html = file_get_contents('post_content.txt'); $doc = new DOMDocument(); $doc->loadHTML($html); // Chọn ra các phần tử a $aElements = $document->getElementsByTagName('a'); foreach ($aElements as $aElement) { // lặp qua các phần tử echo "Link url: " . $aElement->getAttribute('href') . "<br>"; } ?>
Đoạn code trên gọi method getAttribute() từ $aElement object. Method này sẽ trả về giá trị của attribute của phần tử hiện tại. Khi view source trên browser trả về khi chạy file PHP trên b ạn sẽ thấy kết quả như sau:
Link url: /link-1<br>Link url: /link-2<br>
Gán Giá Trị Thuộc Tính Của Phần Tử
Ngoài method getAttribute(), object $aElement của class DOMNode còn cung cấp method setAttribute() để gán giá trị cho thuộc tính của phần tử. Tiếp theo chúng ta sẽ thêm thuộc t ính rel="nofollow" thông qua method này:
<?php $html = file_get_contents('post_content.txt'); ... foreach ($aElements as $aElement) { // lặp qua các phần tử $aElement->setAttribute('rel', 'nofollow'); } // Hiển thị mã HTML echo $doc->saveHTML(); ?>
Bây giờ khi truy cập vào trang PHP trên trình duyệt và view source bạn sẽ thấy kết quả như sau:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> <html><body><h1>Sample post title</h1> <a href="/link-1" rel="nofollow">Link 1</a> <a href="/link-2" rel="nofollow">Link 2</a></body></html>
Tới đây bạn đã tìm hiểu sử dụng DOMDocument của PHP để thực hiện một số thao tác với văn bản HTML. Để coi toàn bộ document cho class DomDocument trong PHP bạn có thể truy cập vào địa chỉ http://php.net/manual/en/class.domdocument.php.