我的经验告诉我 one should not use RegExp to parse HTML/XML ,我完全同意!这是
他们都说某种“使用DOM解析器”,这对我来说很好。但现在我很好奇。这些是如何运作的?
我正在搜索DOMDocument类源代码,但找不到它。
这个问题来自这样一个事实,例如,filter_var()
被认为是使用RegExp验证电子邮件的一个很好的选择,但当你查看源代码时,你会发现它实际上使用了RegExp本身!
那么,如果您要在PHP中构建DOM解析器?你会如何解析HTML?他们是怎么做到的?
答案 0 :(得分:5)
我认为您应该查看文章How Browsers Work: Behind the Scenes of Modern Web Browsers。这是一个冗长的阅读,但值得你花时间。具体来说,HTML Parser部分。
虽然我不能对文章进行公正审判,但在他们有时间阅读和消化这一杰作之前,或许粗略地总结一下。我必须承认,在这个领域我是一个很少有经验的新手。专业为网络开发了大约10年之后,浏览器处理和解释我的代码的方式一直是个黑盒子。
HTML,XHTML,CSS或JavaScript - 随你挑选。他们都有语法和词汇。英语是另一个很好的例子。我们有语法规则,我们希望人们,书籍和其他人遵循。我们还有一个由名词,动词,形容词等组成的词汇。
浏览器通过检查文档的语法及其词汇来解释文档。当遇到它最终无法理解的项目时,它会让你知道(提出异常等)。你和我的共同点也是如此。
我喜欢StackOverflow,但是如果我能改变一件事,那就是绝对破坏......
请注意,在上面的示例中,您将如何立即开始挑选单词之间的单词和关系。一开始就完全有道理,“我喜欢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 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;>
鉴于此引用,我们可以对我们正在解析的任何源进行运行检查。如果作者写tread
而不是thead
,我们就会有一个标准来确定错误。如果问题没有得到解决,我们找不到匹配某些语法和词汇用法的规则,我们会通知作者他们的文件是无效的。
我绝不是在做这种科学正义,但是我希望这有助于 - 如果没有更多 - 足以让你在自己内部找到它并坐下来阅读作为这个答案的开头引用的文章,并且或许坐下来研究我们日常遇到的各种DTD。
答案 1 :(得分:1)
好消息在这里,你不需要重新发明轮子。 libxml library在PHP的DOMDocument扩展中使用,它的源代码可用。 Have a look there我建议。
顺便说一句,正则表达式并不总是错误的,但你需要正确地使用它们直接进入地狱厨房,成为小猫连环杀手或访问chutullu或者如何调用那个人。因此,我建议阅读以下内容:REX: XML Shallow Parsing with Regular Expressions。
但是如果你做的一切正确,正则表达式可以帮助你解析很多东西。只是你应该知道你做了什么。