Webkit之HTML解析

加載部分HTML文本(即主資源)後即可以開始解析HTML元素(對輸入字節流進行逐字掃描,識別HTML元素),最後生成DOM樹,本文只講HTML解析。html

HTML解析部分時序圖:app

其中最爲重要的過程是(1)startToken(2)nextToken(3)endToken(4)constructTreeFromHTMLToken,這裏的4步是循環執行的,當輸入字符結束時,則跳出循環。spa

HTMLTokenizer::nextToken則建立了token,而後能夠根據token建立html元素,解析的整個過程就是一個狀態機.net

HTML解析狀態機:code

初始狀態爲DataState,狀態機結束後會返回一個HTMLToken對象,不一樣的結束方式(上圖中有三個出口一、二、3)HTMLToken的類型也會不一樣。htm

class HTMLToken {
    enum Type {
        Uninitialized,
        DOCTYPE,
        StartTag,
        EndTag,
        Comment,
        Character,
        EndOfFile,
    }; 
} ; 

對於1結束位置:Type=EndOfFile對象

對於2結束位置:Type=Characterblog

對於3結束位置:解析註釋-Type=Comment,解析文檔類型-Type=DOCTYPE,解析標籤(Type=StartTag/EndTag)token

 

子狀態機/解析註釋:資源

 

子狀態機/解析文檔類型:

 

子狀態機/解析標籤名、屬性名、屬性值

 

最後以一個簡單的HTML爲例,描述解析過程:

<!Doctype html>
<!--comment-->
<html>
<body>
<p>First name:</p>
<input type="text"/>
</body>
</html>

 

1.解析文檔類型

'<!Doctype html>',DataState狀態遷移到TagOpenState狀態

'<!Doctype html>',TagOpenState狀態遷移到MarkupDeclarationOpenState狀態

'<!Doctype html>',MarkupDeclarationOpenState狀態遷移到DOCTYPEState狀態

'<!Doctype html>',DOCTYPEState狀態遷移到BeforeDOCTYPENameState狀態

'<!Doctype html>',BeforeDOCTYPENameState狀態遷移到DOCTYPENameState狀態,並執行beginDOCTYPE

'<!Doctype html>',DOCTYPENameState狀態遷移到DOCTYPENameState狀態,並執行appendToName

'<!Doctype html>',結束

二、解析註釋

'<!--comment-->',DataState狀態遷移到TagOpenState狀態

'<!--comment-->',TagOpenState狀態遷移到MarkupDeclarationOpenState狀態

'<!--comment-->',MarkupDeclarationOpenState狀態遷移到CommentStartState狀態

'<!--comment-->',CommentStartState狀態遷移到CommentState狀態,並執行appendToComment

'<!--comment-->',CommentState狀態遷移到CommentState狀態,並執行appendToComment

'<!--comment-->',CommentState狀態遷移到CommentEndDashState狀態

'<!--comment-->',CommentEndDashState狀態遷移到CommentEndState狀態

'<!--comment-->',結束

三、解釋'html'元素

'<html>',DataState狀態遷移到TagOpenState狀態

'<html>',TagOpenState狀態遷移到TagNameState狀態,並執行beginStartTag

'<html>',TagNameState狀態遷移到TagNameState狀態,並執行appendToName

'<html>',結束

四、解釋'body'和'p'元素,同3

六、解析'p'元素內容

'First name:</p>',DataState狀態遷移到DataState狀態,並執行bufferCharacter

'First name:</p>',DataState狀態遷移到DataState狀態,並執行bufferCharacter

'First name:</p>',判斷bufferCharacter是否存在字符,存在則結束

七、解析'/p'元素

'</p>',DataState狀態遷移到TagOpenState狀態

'</p>',TagOpenState狀態遷移到EndTagOpenState狀態

'</p>',EndTagOpenState狀態遷移到TagNameState狀態,並執行beginEndTag

'</p>',結束

八、解析'input'元素

'<input type="text" />',DataState -> TagOpenState

'<input type="text" />',TagOpenState -> TagNameState,並執行beginStartTag

'<input type="text" />',TagNameState -> TagNameState,並執行appendToName

'<input type="text" />',TagNameState -> BeforeAttributeNameState

'<input type="text" />',BeforeAttributeNameState -> AttributeNameState,並執行beginAttribute

'<input type="text" />',AttributeNameState -> AttributeNameState,並執行appendToAttributeName

'<input type="text" />',AttributeNameState -> BeforeAttributeValueState

'<input type="text" />',BeforeAttributeValueState -> AttributeValueDoubleQuotedState

'<input type="text" />',BeforeAttributeValueState -> AttributeValueDoubleQuotedState,並執行appendToAttributeValue

'<input type="text" />',AttributeValueDoubleQuotedState -> AttributeValueDoubleQuotedState,並執行appendToAttributeValue

'<input type="text" />',AttributeValueDoubleQuotedState -> AfterAttributeValueQuotedState,並執行endAttribute

'<input type="text" />',AfterAttributeValueQuotedState-> BeforeAttributeNameState

'<input type="text" />',BeforeAttributeNameState-> SelfClosingStartTagState

'<input type="text" />',結束,並執行setSelfClosing

九、解析'/body'和'/html'元素,同7

 

參考文章:

http://blog.csdn.net/dlmu2001/article/details/5998130

相關文章
相關標籤/搜索