一个 XML 处理很复杂, 但在 .net 却非常方便, 因为系统已提供了 Xml 处理的工具。
一个 Xml 的文件处理是这个格式:
XmlDocument xml = new XmlDocument(); xml.Load("aa.xml"); xml.AppendChild(xml.CreateElement("r"));
但是 HTML 就不如此方便了, 当然 .net 有 HtmlDocument 类 (不知道 ? )
System.Windows.Form.UI.HtmlDocument 这是控件, 内部是 mshtml.dll 完成, 在 web 就无法使用了。
所以非常要做一个 像 XML 一样处理 HTML 的类。
操作 HTML 可以
HtmlDocument html = new HtmlDocument(); html.Load(new Uri(http://www.baidu.com)); html.GetElementById("name").Value = "3";
那就非常好了。
XML 和 HTML 可以解释为继承 HTML 来自 XML
XmlDocument 类的许多成员在 HtmlDocument 也存在
且 HtmlDocument 还有 GetElementById GetElementsByName 的函数
HtmlDocument 的成员不可自定义, 而是有标准的规范的。
首先 要知道:
HTMLNode 其实是1个单链表。
各元素之间 上一个节点指下个节点。 最后一个节点指父节点。
我之所以强调是因为很多人和我一样一直把它作为非链表的。
所以 HtmlNode集合其实是空的,只是提供游走链表的东西。
第二:
和 XML 相比, HTML 处理节点时不同的地方,也是写这个类最困难的地方:
HTML 可以不规范。
如下:
<html><head></html>
这对 XML 来说,是个抛出异常的好地方
XML说: 你给的东西不像话,我不干了, 杂的?
HTML说: 我很友善,我耐心的告诉你啥错了,我帮你修复。
于是 HTML 处理相当复杂。
如果碰到一个 </html> 其父节点不是 <html> 则应加入 </head> 。
类似一个栈, 有进必要出, 没出就抓出来
第三:
<p> 是讨厌的东西,因为 <p></p> 或 <p> 都合法。 需要获得下个节点才能决定<p>
一些<br> 之类的也有额外处理
接下来,可以开做了:
先写 HtmlNode 类
public abstract class HtmlNode { public string NodeName { get; set; } public NodeType NodeType { get; set; } public HtmlNode NextSilding { get; set; } }
然后是 HtmlAttributionCollection, HtmlAttribution
然后是 HtmlElement 类
public class HtmlElement : HtmlNode { HtmlAttributionCollection Attributions; public string TagName {get; set;} }
最后是 HtmlDocument
这些类做好后,继续 词法分析工具
名字为
HtmlParser
这个类负责读取html , 并获取当前位置,如 <html><head id="d">s</html>
将处理为
<html> <head id="d"> s </html>
这样就可知道基本的内容。
最后 HtmlLoader 为节点语法分析
HtmlLoader 有个跟节点(默认 HtmlDocument)
每次载入节点都存至跟节点。 ( 适合 InnerHTML = "" 调用)
HtmlLoader 管理一个栈,负责调整树。
如发现<html> 压入。
发现 </html> 把栈内所有<html>之外的都移除, 再移除 <html>
最后加点常用元素
如 HtmlImageElement , 这样就是完整的 HTML 工具
在系统的 XML 中 使用了 NameTable 实现字符串缓存。
这个缓存由2个优点:
避免同一个 字串占多个位置
比较字串只要比较字符的引用,达到高速的比较。
因此 HTML 同样可以这样操作
最后, 作为 HTML 处理, 当然得提供类似浏览器的一些操作,如表单的提交。
因此 特地准备了 Form 节点, 提供提交函数,将文档值处理后上交。
这可以实现自动填 form ,自动登录等。
当然速度肯定比用控件好多,不过无法处理js部分。