Webkit之HTML解析


加載部分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的類型也會不同。

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

對於1結束位置:Type=EndOfFile

對於2結束位置:Type=Character

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

 

子狀態機/解析注釋:

 

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

 

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

 

最后以一個簡單的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>',結束

2、解析注釋

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

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

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

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

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

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

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

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

3、解釋'html'元素

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

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

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

'<html>',結束

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

6、解析'p'元素內容

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

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

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

7、解析'/p'元素

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

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

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

'</p>',結束

8、解析'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

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

 

參考文章:

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM