2009-12-19 24 views
16

Tôi đang cố gắng phân tích cú pháp một số HTML với DOM trong PHP, nhưng tôi đang gặp một số vấn đề. Đầu tiên, trong trường hợp thay đổi giải pháp, HTML mà tôi có không phải là một trang đầy đủ, thay vào đó, nó chỉ là một phần của nó.Làm cách nào để phân tích cú pháp một phần HTML?

<!-- This is the HTML that I have --><a href='/games/'> 
<div id='game'> 
<img src='http://images.example.com/games.gif' width='300' height='137' border='0'> 
<br><b> Game </b> 
</div> 
<div id='double'> 
<img src='http://images.example.com/double.gif' width='300' height='27' border='0' alt='' title=''> 
</div> 
</a> 

Bây giờ tôi đang cố gắng chỉ nhận được div có id double. Tôi đã thử các mã sau đây, nhưng nó dường như không hoạt động đúng. Tôi có thể làm gì sai?

//The HTML has been loaded into the variable $html 
$dom=new domDocument; 
$dom->loadHTML($html); 
$dom->preserveWhiteSpace = false; 
$keepme = $dom->getElementById('double'); 

$contents = '<div style="text-align:center">'.$keepme.'</a></div>'; 
echo $contents; 
+0

là nó đang làm gì hay không làm gì? –

Trả lời

13

Tôi nghĩ DOMDocument::getElementById sẽ không làm việc trong trường hợp của bạn: (trích dẫn)

Đối với chức năng này để làm việc, bạn sẽ cần một trong hai thiết lập một số thuộc tính ID với DOMElement::setIdAttribute hoặc một DTD trong đó xác định thuộc tính là ID loại.
Trong trường hợp sau, bạn sẽ cần phải xác thực tài liệu của bạn với DOMDocument::validate hoặc DOMDocument->validateOnParse trước khi sử dụng chức năng này.


Một giải pháp mà có thể làm việc được sử dụng một số XPath query để trích xuất các yếu tố bạn đang tìm kiếm.

Trước hết, chúng ta hãy tải phần HTML, giống như bạn lần đầu tiên đã làm:

$dom=new domDocument; 
$dom->loadHTML($html); 
var_dump($dom->saveHTML()); 

Các var_dump được ở đây chỉ để chứng minh rằng phần HTML đã được nạp thành công - đánh giá từ đầu ra của nó, nó có .


Sau đó, instanciate lớp DOMXPath, và sử dụng nó để truy vấn cho các phần tử mà bạn muốn để có được:

$xpath = new DOMXpath($dom); 
$result = $xpath->query("//*[@id = 'double']"); 
$keepme = $result->item(0); 

Bây giờ chúng ta phải yếu tố bạn muốn ;-)


Nhưng , để chèn nội dung HTML của nó vào một phân đoạn HTML khác, trước hết chúng ta phải lấy nội dung HTML của nó.

Tôi không nhớ bất cứ cách nào "dễ dàng" để làm điều đó, nhưng một cái gì đó như thế này Linh hồn làm các trick:

$tempDom = new DOMDocument(); 
$tempImported = $tempDom->importNode($keepme, true); 
$tempDom->appendChild($tempImported); 
$newHtml = $tempDom->saveHTML(); 
var_dump($newHtml); 

Và ... Chúng tôi có nội dung HTML của bạn double<div>:

string '<div id="double"> 
<img src="http://images.example.com/double.gif" width="300" height="27" border="0" alt="" title=""> 
</div> 
' (length=125) 


Bây giờ, bạn chỉ cần phải làm bất cứ điều gì bạn muốn với nó ;-)

0

HTML Tidy phải có khả năng "sửa chữa" các tài liệu HTML bị hỏng và bị phân mảnh, biến chúng thành một cái gì đó có thể được phân tích với các công cụ khác

http://devzone.zend.com/article/761

Phần mở rộng Tidy là mới trong PHP 5, và có sẵn từ phiên bản PHP 5.0b3 trở lên. Nó dựa trên thư viện TidyLib và cho phép nhà phát triển xác thực, sửa chữa và phân tích cú pháp tài liệu HTML, XHTML và XML từ bên trong PHP.

3

Từ DomDocument::getElementById

Đối với chức năng này để làm việc, bạn sẽ cần một trong hai thiết lập một số thuộc tính ID với DOMElement :: setIdAttribute hoặc một DTD trong đó xác định một thuộc tính là loại ID . Trong trường hợp sau, bạn cần để xác thực tài liệu của mình với DOMDocument :: validate hoặc DOMDocument-> validateOnParse trước bằng cách sử dụng chức năng này.

Đối với một số thông tin bổ sung

Và vì ai đó sẽ đề cập đến làm việc đó với một Regular Expression sớm hay muộn, đây là mô hình bạn có thể sử dụng: /<div id='double'>(.*)<\/div>/simU

Trong tiện ích bổ sung tion, bạn chỉ có thể sử dụng các hàm chuỗi thông thường để trích xuất phần div, ví dụ:

$div = strstr($html, '<div id="double">'); 
$div = substr($div, 0, strpos($div, '</div>') + 6); 
echo $div; 

Trong khi tôi đồng ý, bạn không nên sử dụng RegEx hoặc String chức năng cho phân tích HTML hay XML, tôi thấy nó hoàn toàn không quan trọng để làm như vậy, miễn là mối quan tâm duy nhất của bạn là để có được div đơn này từ những mảnh vỡ. Giữ nó đơn giản.

+1

Trừ khi có tất cả các thẻ div lồng nhau.Cụm từ thông dụng là * không * để phân tích cú pháp html. – troelskn

+0

Tôi sẽ đồng ý nếu anh ta thực sự * phân tích cú pháp * đoạn đó. nhưng anh ta chỉ muốn trích xuất một mảnh được xác định rõ ràng từ nó. Nó không giống như anh ta đang đi qua DOM, vì vậy tôi đoán nó là ok để điều trị các mảnh như một chuỗi. – Gordon

+0

Bên cạnh đó, tôi đã chỉ cho anh ta SimpleHTML trong câu đầu tiên. – Gordon

0

Một tài liệu XML chỉ có thể có một phần tử ở cấp cơ sở. Có thể, trình phân tích cú pháp HTML có yêu cầu tương tự. Hãy thử gói nội dung trong một thẻ <body/>.

Dường như đó là thứ khác. This page mô tả những gì có thể là nguyên nhân. Tôi khuyên bạn nên sử dụng XPath để lấy phần tử.

-1

Phân đoạn là HTML, nhưng để được phân tích cú pháp qua DOM, nó phải XHTML. Mọi thẻ mở đều phải đóng.

Trong trường hợp của bạn có nghĩa là bạn nên thay thế <br> với <br /><img ... > với <img ... />

+0

Điều đó thực sự không đúng. $ dom-> loadHTML ("


") hoạt động tốt và không phân tích cú pháp. Trên thực tế, $ dom-> saveXML() sẽ hiển thị cho bạn đầu ra với các thẻ được đóng đúng cách. –

+0

Tất cả phụ thuộc vào thư viện bạn sử dụng. Trong python: xml.dom.minidom.parseString ("
") -> trả về một ngoại lệ. xml.dom.minidom.parseString ("
") hoạt động. Tôi muốn có đầu vào ở định dạng chính xác ở vị trí đầu tiên hơn là dựa vào thư viện để phân tích cú pháp đầu vào không chính xác như tôi mong đợi. – filippo

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