加载部分HTML文本(即主资源)后便可以开始解析HTML元素(对输入字节流进行逐字扫描,识别HTML元素),最后生成DOM树,本文只讲HTML解析。
HTML解析部分时序图:
其中最为重要的过程是(1)startToken(2)nextToken(3)endToken(4)constructTreeFromHTMLToken,这里的4步是循环执行的,当输入字符结束时,则跳出循环。
HTMLTokenizer::nextToken则创建了token,然后可以根据token创建html元素,解析的整个过程就是一个状态机
HTML解析状态机:
初始状态为DataState,状态机结束后会返回一个HTMLToken对象,不同的结束方式(上图中有三个出口1、2、3)HTMLToken的类型也会不同。
classHTMLToken {enumType {
Uninitialized,
DOCTYPE,
StartTag,
EndTag,
Comment,
Character,
EndOfFile,
};
} ;
对于1结束位置:Type=EndOfFile
对于2结束位置:Type=Character
对于3结束位置:解析注释-Type=Comment,解析文档类型-Type=DOCTYPE,解析标签(Type=StartTag/EndTag)
子状态机/解析注释:
子状态机/解析文档类型:
子状态机/解析标签名、属性名、属性值
最后以一个简单的HTML为例,描述解析过程:
First name:
1.解析文档类型
'',DataState状态迁移到TagOpenState状态
'',TagOpenState状态迁移到MarkupDeclarationOpenState状态
'html>',MarkupDeclarationOpenState状态迁移到DOCTYPEState状态
'',DOCTYPEState状态迁移到BeforeDOCTYPENameState状态
'html>',BeforeDOCTYPENameState状态迁移到DOCTYPENameState状态,并执行beginDOCTYPE
'html>',DOCTYPENameState状态迁移到DOCTYPENameState状态,并执行appendToName
'html>',结束
2、解析注释
'',DataState状态迁移到TagOpenState状态
'',TagOpenState状态迁移到MarkupDeclarationOpenState状态
'',MarkupDeclarationOpenState状态迁移到CommentStartState状态
'',CommentStartState状态迁移到CommentState状态,并执行appendToComment
'',CommentState状态迁移到CommentState状态,并执行appendToComment
'',CommentState状态迁移到CommentEndDashState状态
'',CommentEndDashState状态迁移到CommentEndState状态
'',结束
3、解释'html'元素
'',DataState状态迁移到TagOpenState状态
'',TagOpenState状态迁移到TagNameState状态,并执行beginStartTag
'',TagNameState状态迁移到TagNameState状态,并执行appendToName
'',结束
4、解释'body'和'p'元素,同3
6、解析'p'元素内容
'First name:
',DataState状态迁移到DataState状态,并执行bufferCharacter'First name:
',DataState状态迁移到DataState状态,并执行bufferCharacter'First name:
',判断bufferCharacter是否存在字符,存在则结束7、解析'/p'元素
'
',DataState状态迁移到TagOpenState状态'
',TagOpenState状态迁移到EndTagOpenState状态'
',EndTagOpenState状态迁移到TagNameState状态,并执行beginEndTag'
',结束8、解析'input'元素
'',DataState -> TagOpenState
'',TagOpenState -> TagNameState,并执行beginStartTag
'',TagNameState -> TagNameState,并执行appendToName
'',TagNameState -> BeforeAttributeNameState
'',BeforeAttributeNameState -> AttributeNameState,并执行beginAttribute
'',AttributeNameState -> AttributeNameState,并执行appendToAttributeName
'',AttributeNameState -> BeforeAttributeValueState
'',BeforeAttributeValueState -> AttributeValueDoubleQuotedState
'',BeforeAttributeValueState -> AttributeValueDoubleQuotedState,并执行appendToAttributeValue
'',AttributeValueDoubleQuotedState -> AttributeValueDoubleQuotedState,并执行appendToAttributeValue
'',AttributeValueDoubleQuotedState -> AfterAttributeValueQuotedState,并执行endAttribute
'',AfterAttributeValueQuotedState-> BeforeAttributeNameState
'',BeforeAttributeNameState-> SelfClosingStartTagState
'',结束,并执行setSelfClosing
9、解析'/body'和'/html'元素,同7