一种基于状态机的 DOM 树生成技术(2)

简介: 一种基于状态机的 DOM 树生成技术(2)

 

在上一篇一种基于状态机的 DOM 树生成技术(1)我们给大家介绍了状态机的基本概念、设计思路以及基于 Java 语言的实现,希望大家能够了解相关知识点。状态机是我们后续介绍 DOM 树生成的关键技术,后面几篇博客都将基于状态机来实现。所以请大家务必掌握,如果还有不清楚的地方可以阅读之前的文章,也非常欢迎大家关注微信公众号,及时了解最新文章。

 

首先我们还是来回顾一下我们的任务,给定一个 HTML 文件,生成该文件的 DOM 树。一个 HTML 文件即一段采用 HTML 规则编写的字符串,如"<html><body><p>hello</p></body></html>"

 

那么如何根据这样的一段字符串生成 DOM 树呢?

 

1 分词

我们称第一阶段为分词,要想最终生成一颗 DOM树,我们并不是一个字符一个字符的处理,而是将HTML 字符串首先进行分词,然后再一个分词一个分词的处理。

 

我们定义以下类型的分词,称每一个分词为 Token

StartTag:开始标签如<html>

EndTag:结束标签如</html>

CharacterStartTag EndTag 之间的内容如 hello

EOF:结束标记。

 

针对这个字符串"<html><body><p>hello</p></body></html>",我们可以得到以下的分词:

StartTag:<html>

StartTag:<body>

StartTag:<p>

Character:hello

EndTag:</p>

EndTag:</body>

EndTag:</html>

 

现在我们已经明确了要达到什么目标,那么接下来如何实现将 HTML 字符串转化为一个个的分词呢?

 

2 利用状态机实现分词

 

在上一篇博客我们给大家介绍了状态机的基本知识,本节我们将介绍一种基于状态机的分词技术。

 

上图为实现第一节分词而设计的一个状态机,这个状态机屏蔽了很多错误处理环节,目的是为了让我们的描述更加简洁,让大家能够更加关注核心问题。我们来看一下这个状态机是如何设计的。

 

DATA:起始状态。

当输入字符为'-1'表示已经到达字符串的结尾,此时识别到一个分词 EOF

当输入字符为'<',进入 TagOpen 状态。

 输入字符为其他字符时,此时识别到一个分词 Character

 

TagOpen:

当输入字符为'/'进入到 EndTagOpen 状态。

检测当前字符是否为字母,如果是则进入 TagName

 

EndTagOpen:

检测当前字符是否为字母,如果是则进入 TagName

 

TagName:

该状态将一次性读取所有字母,直到遇到'/''>'为止。

当下一个输入字符为'>',此时已经识别到一个HTML 标签,并将进入到 DATA

 

 

接下来我们就将以一个实例来描述状态机的运行过程。

<html><body><p>hello</p></body></html>

当前输入为'<',将进入TagOpen

 

<html><body><p>hello</p></body></html>

TagOpen检测到下一个字符为字母'h',进入 TagName

TagName 一次性读取所有的字母 "html",此时识别到一个 StartTag,并做 token 识别完成标记。下一个输入为'>',进入 DATA

以上就是识别一个StartTag 的流程。body p 类似,不再赘述。

 

<html><body><p>hello</p></body></html>

上述流程已经识别完成了三个StartTag 分词,分别是<html><body> < p>

当前状态为 DATA且下一个输入字符为 'h',一次性读取所有的字母'hello'。此时识别到一个分词 Character,并做分词结束标记。

 

<html><body><p>hello</p></body></html>

当前状态为 DATA且下一个输入字符为'<',进入 TagOpen

 

<html><body><p>hello</p></body></html>

当前状态为 TagOpen,且下一个输入字符为'/',进入 EndTagOpen,当前标签类型为 EndTag

检测到下一个字符为字母,故进入 TagName

 

<html><body><p>hello</p></body></html>

TagName 状态下不停的读取字母。当遇到字符'>',标记这是一个分词,并进入到 DATA

 

3 总结

本文介绍了一种基于状态机的分词技术,设计了一个能够识别HTML 字符串中分词的状态机,并对状态机的运行流程做了细致的分析。

 

后续的DOM树生成将基于上述分词。下一讲我们将介绍如何利用 Java 语言实现这样的分词技术。如您在博客阅读的过程遇到任何的疑问,欢迎在下方留言。

 

本文所有代码可在以下 git 库中 day02模块中找到,git 地址为:

https://gitee.com/gschen/sctu-treebuilder.git

感兴趣的同学可以提前阅读代码。


其他精彩文章:

史上最详细的JNI入门教程HelloNative

什么是BS 架构(一)

Volley源码分析(1)

50行代码实现简单的网站服务器

50行代码实现网站服务器 2

50行代码实现网站服务器 3

 

目录
相关文章
|
6天前
|
缓存 JavaScript 前端开发
【JavaScript 技术专栏】DOM 操作全攻略:从基础到进阶
【4月更文挑战第30天】本文深入讲解JavaScript与DOM交互,涵盖DOM基础、获取/修改元素、创建/删除元素、事件处理结合及性能优化。通过学习,开发者能掌握动态改变网页内容、结构和样式的技能,实现更丰富的交互体验。文中还讨论了DOM操作在实际案例、与其他前端技术结合的应用,助你提升前端开发能力。
|
6天前
|
存储 JavaScript 前端开发
理解DOM树的加载过程
理解DOM树的加载过程
19 0
|
6天前
|
XML JavaScript 数据格式
XML DOM 遍历节点树
该文介绍了如何遍历XML文档的DOM节点树。通过循环节点,可以访问并处理每个元素,如提取值。示例代码展示了加载XML字符串到`xmlDoc`后,遍历根元素的所有子节点,打印出节点名及文本值,例如:&quot;title: Everyday Italian&quot;、&quot;author: Giada De Laurentiis&quot;和&quot;year: 2005&quot;。
|
1天前
|
XML JavaScript 前端开发
XML DOM 遍历节点树
```markdown 遍历XML DOM节点树涉及在文档中循环移动。以下示例展示如何遍历并显示所有子节点的名称和值: ``` ```xml &lt;!DOCTYPE html&gt; &lt;output&gt; title: Everyday Italian author: Giada De Laurentiis year: 2005 &lt;/output&gt; ``` ```javascript // 加载XML到xmlDoc // 获取根元素子节点 // 对每个子节点,打印节点名和文本节点值 ```
|
3天前
|
XML JavaScript 数据格式
XML DOM 遍历节点树
该文介绍了如何遍历XML文档的节点树。通过循环移动,可以访问并处理每个节点,例如提取元素值。提供的实例展示了如何加载XML到DOM,获取根元素的子节点,并打印其名称和值,以“title: Everyday Italian, author: Giada De Laurentiis, year: 2005”为例。
|
6天前
|
XML JavaScript 数据格式
XML DOM 遍历节点树
该文介绍了如何遍历XML文档的节点树。通过循环移动,可以访问每个元素并提取其值。示例代码展示了一个XML文档的遍历过程,输出了所有子节点的名称和值,如&quot;title: Everyday Italian&quot;等。首先加载XML到xmlDoc,然后获取根元素的子节点,并依次打印节点名及文本内容。
|
6天前
|
XML JavaScript 数据格式
Beautiful Soup 库的工作原理基于解析器和 DOM(文档对象模型)树的概念
【5月更文挑战第10天】Beautiful Soup 使用解析器(如 html.parser, lxml, html5lib)解析HTML/XML文档,构建DOM树。它提供方法查询和操作DOM,如find(), find_all()查找元素,get_text(), get()提取信息。还能修改DOM,添加、修改或删除元素,并通过prettify()输出格式化字符串。它是处理网页数据的利器,尤其在处理不规则结构时。
38 2
|
6天前
|
XML JavaScript 前端开发
XML DOM 遍历节点树
该示例展示了如何遍历XML文档的节点树。通过DOMParser解析XML字符串得到xmlDoc,然后遍历根节点的子节点,显示每个节点的名称及其文本值。输出结果为:&quot;title: Everyday Italian&quot;, &quot;author: Giada De Laurentiis&quot;, &quot;year: 2005&quot;。代码使用JavaScript实现,循环遍历并更新HTML元素`&lt;p id=&quot;demo&quot;&gt;&lt;/p&gt;`的内容。
|
6天前
|
JavaScript 前端开发 UED
【Web 前端】如何将一个 HTML 元素添加到 DOM 树中的?
【5月更文挑战第2天】【Web 前端】如何将一个 HTML 元素添加到 DOM 树中的?
|
6天前
|
前端开发 JavaScript
浏览器通过构建DOM树来解析HTML代码
【4月更文挑战第30天】浏览器通过构建DOM树来解析HTML代码
27 1