我的经验告诉我,不应该使用RegExp来解析HTML/XML,我完全同意!它的
他们都说某种"使用DOM解析器",这对我来说很好.但现在我很好奇.这些如何运作?
我正在搜索DOMDocument类源,但找不到它.
这个问题来自于这样一个事实,filter_var()
例如,被认为是使用RegExp验证电子邮件的一个很好的选择,但是当你查看源代码时,你会发现它实际上使用了RegExp本身!
那么,如果你要在PHP中构建DOM解析器?你会如何解析HTML?他们是如何做到的呢?
我想你应该查看文章浏览器如何工作:现代Web浏览器的幕后故事.这是一个冗长的阅读,但值得你花时间.具体来说,HTML Parser部分.
虽然我不能把这篇文章公正化,但是在他们有时间阅读和消化这一杰作之前,或许粗略地总结一下.我必须承认,在这个领域我是一个很少有经验的新手.专业为网络开发了大约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">
Run Code Online (Sandbox Code Playgroud)
这定义了标题实体.只要我遵守XHTML的语法,我就可以在我的文档(<h1>Hello World</h1>
)中使用其中任何一个.但是,如果我尝试制作一个,比如说H7
,浏览器会偶然发现词汇"外来",并通知我:
"第7行,第8列:元素"h7"undefined"
也许在解析我们遇到的文档时<table
.我们知道,我们现在处理的是一个table
元素,它有自己的一套词汇如tbody
,tr
等我们只要知道的语言,语法规则等,当事情是,我们知道错了.回到XHTML 1.0 Strict 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;>
Run Code Online (Sandbox Code Playgroud)
鉴于此引用,我们可以对我们正在解析的任何源进行运行检查.如果作者写道tread
,而不是thead
,我们有一个标准,通过它我们可以确定是错误的.如果问题未得到解决,我们找不到匹配某些语法和词汇用法的规则,我们会通知作者他们的文档无效.
我绝不会做这种科学正义,但我希望这有助于 - 如果没有更多 - 足以让你在自己内部找到它并坐下阅读作为这个答案的开头引用的文章,也许坐下来并研究我们每天遇到的各种DTD.