<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] # HTML ## HTML文法定義(The HTML grammar definition) W3C組織制定規范定義了HTML的詞匯表和語法。 <br> <br> ## 非上下文無關文法(Not a context free grammar) 正如在解析簡介中提到的,上下文無關文法的語法可以用類似BNF的格式來定義。 <br> 不幸的是,所有的傳統解析方式都不適用于html(當然我提出它們并不只是因為好玩,它們將用來解析css和js),html不能簡單的用解析所需的上下文無關文法來定義。 <br>   Html有一個正式的格式定義——DTD(Document Type Definition文檔類型定義)——但它并不是上下文無關文法,html更接近于xml,現在有很多可用的xml解析器,html有個xml的變體——xhtml,它們間的不同在于,html更寬容,它允許忽略一些特定標簽,有時可以省略開始或結束標簽。總的來說,它是一種soft語法,不像xml呆板、固執。 <br>   顯然,這個看起來很小的差異卻帶來了很大的不同。一方面,這是html流行的原因——它的寬容使web開發人員的工作更加輕松,但另一方面,這也使很難去寫一個格式化的文法。所以,html的解析并不簡單,它既不能用傳統的解析器解析,也不能用xml解析器解析。 <br> <br> ## HTML DTD Html適用DTD格式進行定義,這一格式是用于定義SGML家族的語言,包括了對所有允許元素及它們的屬性和層次關系的定義。正如前面提到的,html DTD并沒有生成一種上下文無關文法。 <br> DTD有一些變種,標準模式只遵守規范,而其他模式則包含了對瀏覽器過去所使用標簽的支持,這么做是為了兼容以前內容。最新的標準DTD在[鏈接](http://www.w3.org/TR/html4/strict.dtd ) <br> <br> # DOM樹 輸出的樹,也就是解析樹,是由DOM元素及屬性節點組成的。DOM是文檔對象模型的縮寫,它是html文檔的對象表示,作為html元素的外部接口供js等調用。 樹的根是“document”對象。 DOM和標簽基本是一一對應的關系,例如,如下的標簽: ~~~ <html> <body> <p> Hello DOM </p> <div><img src=”example.png” /></div> </body> </html> ~~~ 將會被轉換為下面的DOM樹: ![](https://box.kancloud.cn/dc9dbc56a001f62b528c5a888962d975_400x219.png) <br> 和html一樣,DOM的規范也是由W3C組織制定的。訪問[http://www.w3.org/DOM/DOMTR](http://www.w3.org/DOM/DOMTR),這是使用文檔的一般規范。一個模型描述一種特定的html元素,可以在[http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/idl-definitions.htm](http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/idl-definitions.htm)查看html定義。 <br> <br> # 解析算法(The parsing algorithm) 正如前面章節中討論的,hmtl不能被一般的自頂向下或自底向上的解析器所解析。原因是: * 這門語言本身的寬容特性 * 瀏覽器對一些常見的非法html有容錯機制 * 解析過程是往復的,通常源碼不會在解析過程中發生改變,但在html中,腳本標簽包含的“document.write”可能添加標簽,這說明在解析過程中實際上修改了輸入。 <br> 不能使用正則解析技術,瀏覽器為html定制了專屬的解析器。 Html5規范中描述了這個解析算法,算法包括兩個階段——符號化及構建樹。 符號化是詞法分析的過程,將輸入解析為符號,html的符號包括開始標簽、結束標簽、屬性名及屬性值。 符號識別器識別出符號后,將其傳遞給樹構建器,并讀取下一個字符,以識別下一個符號,這樣直到處理完所有輸入。 ![](https://box.kancloud.cn/b4dc4e548d9012c25d5a5f0b4e5f17e5_308x400.png) <br> <br> # 符號識別算法(The tokenization algorithm) ## 詞(token)是如何被拆分的 * 拆分:最小有意義單元 - token(詞) * 詞的種類大約只有標簽開始、屬性、標簽結束、注釋、CDATA 節點... * eg: ~~~ <p?class="a">text text text</p> ~~~ * <p“標簽開始”的開始; * class=“a” 屬性 * `>` “標簽開始”的結束; * text text text 文本; * /p>標簽結束 ![](https://box.kancloud.cn/095422978cadcc6de9064bd05b1d927a_624x252.png) <br> # 樹的構建算法 ## 狀態機 ![](https://box.kancloud.cn/2d5744f3ba248f43604ab759907ab48e_768x739.png) * 為什么使用:我們每讀入一個字符,其實都要做一次決策,而且這些決定是跟“當前狀態”有關的 * 定義:把每個詞的“特征字符”逐個拆開成獨立狀態,然后再把所有詞的特征字符鏈合并起來,形成一個聯通圖結構。 * 絕大多數語言的詞法部分都是用狀態機實現的,HTML 官方文檔規定了 80 個狀態 * 最終把字符流拆分成詞 <br> ## 構建 DOM 樹 通過棧來實現,當接收完所有輸入,棧頂就是最后的根節點,我們 DOM 樹的產出,就是這個 stack 的第一項。 <br> 實現一個Node 類,所有的節點都會是這個 Node 類的實例。不一樣的 HTML 節點對應了不同的 Node 的子類,此處的實現,我們進行簡化,只把 Node 分為 Element 和 Text ~~~ function Element(){ this.childNodes = []; } function Text(value){ this.value = value || ""; } ~~~ * 規則: * token中`tag start`和`tag end`需要成對實現,使用的棧正是用于匹配開始和結束標簽的方案(編譯原理技巧) * Text 節點:把相鄰的 Text 節點合并起來,當詞(token)入棧時,檢查棧頂是否是 Text 節點,果是的話就合并 Text 節點 * 構建過程: (默認:源代碼完全遵循 xhtml,HTML 具有很強的容錯能力,奧妙在于當 tag end 跟棧頂的 start tag 不匹配的時候如何處理,暫時不考慮) * 棧頂元素就是當前節點; * 遇到屬性,就添加到當前節點; * 遇到文本節點,如果當前節點是文本節點,則跟文本節點合并,否則入棧成為當前節點的子節點; * 遇到注釋節點,作為當前節點的子節點; * 遇到 tag start 就入棧一個節點,當前節點就是這個節點的父節點 * 遇到 tag end 就出棧一個節點(還可以檢查是否匹配) <br> ## 瀏覽器容錯(Browsers error tolerance) 你從來不會在一個html頁面上看到“無效語法”這樣的錯誤,瀏覽器修復了無效內容并繼續工作。 <br> 以下面這段html為例: ~~~ <html> <mytag> </mytag> <div> <p> </div> Really lousy HTML </p> </html> ~~~ <br> 這段html違反了很多規則(mytag不是合法的標簽,p及div錯誤的嵌套等等),但是瀏覽器仍然可以沒有任何怨言的繼續顯示,它在解析的過程中修復了html出現的錯誤。 <br> 瀏覽器都具有錯誤處理的能力,但是,另人驚訝的是,這并不是html最新規范的內容,就像書簽及前進后退按鈕一樣,它只是瀏覽器長期發展的結果。一些比較知名的非法html結構,在許多站點中出現過,瀏覽器都試著以一種和其他瀏覽器一致的方式去修復。 <br>   Html5規范定義了這方面的需求,webkit在html解析類開始部分的注釋中做了很好的總結。 <br>   解析器將符號化的輸入解析為文檔并創建文檔,但不幸的是,我們必須處理很多沒有很好格式化的html文檔,至少要小心下面幾種錯誤情況。 <br>   1. 在未閉合的標簽中添加明確禁止的元素。這種情況下,應該先將前一標簽閉合   2. 不能直接添加元素。有些人在寫文檔的時候會忘了中間一些標簽(或者中間標簽是可選的),比如HTML HEAD BODY TR TD LI等   3. 想在一個行內元素中添加塊狀元素。關閉所有的行內元素,直到下一個更高的塊狀元素   4. 如果這些都不行,就閉合當前標簽直到可以添加該元素。 <br> ## 解析結束時的處理(Action when the parsing is finished)  在這個階段,瀏覽器將文檔標記為可交互的,并開始解析處于延時模式中的腳本——這些腳本在文檔解析后執行。  文檔狀態將被設置為完成,同時觸發一個load事件。  Html5規范中有符號化及構建樹的完整算法(http://www.w3.org/TR/html5/syntax.html#html-parser)。 <br> <br> # 參考資料 [瀏覽器工作原理(四):HTML解析器 HTML Parser](https://blog.csdn.net/lxcao/article/details/52860746) 重學前端
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看