2012-05-05 91 views
7

我的經驗告訴我,one should not use RegExp to parse HTML/XML,我完全同意!這是DOM解析器如何實現?

  • 凌亂
  • 不穩健和容易折斷
  • 純粹的邪惡

他們都說「使用DOM解析器」某種形式的,它通過我的罰款。但現在我很好奇。這些工作如何?

我正在搜索DOMDocument類源,並找不到它。

這個問題來自filter_var()這個事實,它被認爲是用RegExp驗證電子郵件的一個很好的選擇,但是當你看到源代碼時,你會發現它實際上使用了RegExp本身!

那麼,如果您要在PHP中構建DOM解析器?你將如何去解析HTML?他們是如何做到的呢?

+2

DOM解析器通常實現爲標記器。如果您可以閱讀C#,那麼[HTML Agility Pack](http://htmlagilitypack.codeplex.com)的源代碼可以使該方法清晰。 – Oded

+4

關於'filter_var()':沒有人說過你不應該用正則表達式來驗證電子郵件地址。事實上,爲這個*正確的任務編寫正則表達式非常困難,需要大量的研究工作。所以這裏有成千上萬的可怕實現。這就是爲什麼你應該簡單地使用'filter_var()'。 – kapa

+0

如果你正在處理XHTML,一個普通的XML解析器可以正常工作。 – Niko

回答

5

我想你應該看看文章How Browsers Work: Behind the Scenes of Modern Web Browsers。這是一個冗長的閱讀,但非常值得你的時間。具體來說,HTML分析器部分。

雖然我不能做文章正義,但也許一個粗略的總結將是一個很好的舉措,直到他們有時間閱讀和消化該傑作。但我必須承認,在這方面我是一個經驗不多的新手。在爲專業網站開發了大約10年之後,瀏覽器處理和解釋我的代碼的方式一直是黑盒子。

HTML,XHTML,CSS或JavaScript - 請選擇。他們都有語法和詞彙。英語是另一個很好的例子。我們有語法規則,我們期望人們,書籍和其他內容能夠遵循。我們還有一個由名詞,動詞,形容詞等組成的詞彙。

瀏覽器通過檢查文檔的語法及其詞彙來解釋文檔。當它遇到項目它最終不理解,它會讓你知道(引發異常等)。你和我在普通話上也是這樣做的。

我愛StackOverflow的,但如果我可以改變一件事它會被打破absolutamente ...

注意上面如何立即開始挑開詞與詞之間的單詞和關係的例子。開始意義非凡,「我愛StackOverflow」。然後我們來「......如果我可以改變」,我們立即停止。 「改變」不屬於這裏。這可能是作者改爲「改變」。現在的詞彙是正確的,但語法是錯誤的。稍後我們會遇到「be be」,這也可能違反語法規則,並且我們會遇到單詞「absolutamente」,這不是英語詞彙的一部分 - 另一個錯誤。

從DOCTYPE的角度考慮所有這些。我現在已經在我的第二臺監視器上開放了XHTML 1.0 Strict Doctype的源代碼。它的內部結構如下:

<!ENTITY % heading "h1|h2|h3|h4|h5|h6"> 

這定義了標題實體。只要我堅持使用XHTML的語法,我可以在我的文檔(<h1>Hello World</h1>)中使用這些語法中的任何一個。但是,如果我努力使一升上來,說H7,瀏覽器會絆倒的詞彙爲「外國」,並告訴我:

「7號線,8列:元素‘H7’未定義」

也許在解析文檔時遇到<table。我們知道我們現在正在處理一個table元素,該元素有其自己的一組詞彙,如tbody,tr等。只要我們知道語言,語法規則等,就可以知道什麼時候出了問題。返回到XHTML 1.0嚴格的DOCTYPE,我們發現如下:

<!ELEMENT table 
    (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))> 
<!ELEMENT caption %Inline;> 
<!ELEMENT thead (tr)+> 
<!ELEMENT tfoot (tr)+> 
<!ELEMENT tbody (tr)+> 
<!ELEMENT colgroup (col)*> 
<!ELEMENT col  EMPTY> 
<!ELEMENT tr  (th|td)+> 
<!ELEMENT th  %Flow;> 
<!ELEMENT td  %Flow;> 

鑑於這種參照,我們可以保持對任何來源我們分析一個正在運行的檢查。如果作者寫入tread而不是thead,我們有一個標準,我們可以確定這是錯誤的。如果問題沒有得到解決,而且我們無法找到符合某些語法和詞彙用法的規則,我們會通知作者他們的文檔是無效的。

我絕對不是在做這種科學正義,但是我希望這能夠服務 - 如果沒有其他的東西 - 足以讓您在自己的內部找到自己坐下來閱讀引用這篇答案的開頭的文章,也許坐下來研究我們日常遇到的各種DTD。

1

好消息是在這裏,你不需要重新發明輪子。在PHP的DOMDocument擴展中使用libxml library,它的源代碼可用。 Have a look there我建議。

順便說一下,正則表達式並不總是錯的,但是你需要使用它們,其他的你直接進入地獄廚房,成爲一隻小貓連環殺手或者訪問chutullu或者這個人被稱爲。我建議以下閱讀:REX: XML Shallow Parsing with Regular Expressions

但是,如果你做的一切正確,正則表達式可以幫助你很多解析。只是你應該知道你在做什麼。

+0

就像我所說的,我不是想重新發明輪子,我只是對輪子的工作原理感到好奇。此外,我試圖找到DOMDocument的來源,並找不到它。 –

+0

我鏈接了libxml的源代碼。看看他們網站上架構的描述,這個項目相當大。還有一個htmlpurifier項目,它是一個用PHP IIRC編寫的HTML解析器。 – hakre