HTML解析

2016/2/23 posted in  others

HTML5解析由两部分组成:分词与构建树。

分词属于语法分析部分,它把输入解析成符号序列。在HTML中符号就是开始标签,结束标签,属性名称和属性值。

分词算法

分词算法可以用状态机来描述。每一个状态从输入流中消费一个或者多个字符,并根据它们更新下一状态。

决策受当前符号状态和树的构建状态影响。这意味着同样的字符可能会产生不同的结果,取决于当前的状态。

<html>
    <body>
        Hello world
    </body>
</html>

初始状态是Data state,当遇到<时状态改为Tag open state。吃掉a-z字符组成的符号后产生了Start tag token,状态变更为Tag name state。我们一直保持此状态,直到遇到>。每个字符都被追加到新的符号名上。在我们的例子中,解出的符号就是html

当碰到>时,当前符号完成,状态改回Data state<body>标签将会以同样的方式处理。现在htmlbody标签都完成了,我们回到Data state状态。吃掉HHello world第一个字母)时会产生一个字符符号,直到碰到</body><符号,我们就完成了一个字符符号Hello world

现在我们回到Tag open state状态。吃掉下一个输入/时会产生一个end tag token并变更为Tag name state状态。同样,此状态保持到我们碰到>时。这时新标签符号完成,我们又回到Data state。同样</html>也会被这样处理。

树的构建算法

当分词解析器被创建时,文档对象也会被创建。

在树的创建过程中DOM树的根节点(Document)将被修改,元素被添加到上面去。每个分词器完成的节点都会被树构建器处理。

除了把元素添加到DOM树外,它还会被添加到一个开放元素堆栈。这个堆栈用于纠正嵌套错误和标签未关闭错误。

<html>
    <body>
        Hello world
    </body>
</html>

树的构建过程中,输入就是分词过程中得到的符号序列。第一个模式叫initial mode。接收html符号后会变成before html模式并重新处理此模式中的符号。这会创建一个HTMLHtmlElement元素并追加到根文档节点。

然后状态改变为before head。我们收到body时,会隐式创建一个HTMLHeadElement,尽管我们没有这个标签,它也会被创建并添加到树中。

现在我们进入in head模式,然后是after headBody会被重新处理,创建HTMLBodyElement元素并插入,然后进入in body模式。

字符符号Hello world收到后会创建一个Text节点,所有字符都被一一追加到上面。

收到body结束标签后进入after body模式,收到html结束标签后进入after after body模式。所有符号处理完后将终止解析。