zoukankan      html  css  js  c++  java
  • 浏览器是怎样工作的二:渲染引擎 HTML解析(3)(转)

    本文作者:hfliu

    文章来源:携程UED

    解析算法

    如我们前面看到的,HTML无法使用自上而下或自下而上的解析器来解析。

    理由如下:

    1. 语言的宽容特点
    2. 浏览器需要对无效HTML提供容错性的事实。
    3. 解析过程的反复。通常解析过程中源码不会变化。但在HTML中,script标签包含"document.write"时可以添加内容,即解析过程实际上还会改变源码。

    浏览器创建了自己的解析器来解析HTML文档。

    HTML5规范里对解析算法有具体的说明,解析由两部分组成:分词与构建树。

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

    分词器识别这些符号并将其送入树构建者,然后继续分析处理下一个符号,直到输入结束。

    图 6: HTML解析流程 (源自HTML5规范)

    分词算法

    算法的输出是HTML符号。算法可以用状态机来描述。 每一个状态从输入流中消费一个或多个字符,并根据它们更新下一状态。决策受当前符号状态和树的构建状态影响。这意味着同样的字符可能会产生不同的结果,取决于当前的状态。算法太复杂,我们用一个例子来看看它的原理。

    基础示例,分析下面的标签:

    1. <html>  
    2.     <body>  
    3.         Hello world   
    4.     body>  
    5.  html>  

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

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

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

    图 9: 示例输入源的分词处理

    树的构建算法

    当解析器被创建时,文档对象也被创建了。在树的构建过程中DOM树的根节点(Documen)将被修改,元素被添加到上面去。每个分词器完成的节点都会被树构建器处理。规范中定义了每一个符号与哪个DOM对象相关。除了把元素添加到DOM树外,它还会被添加到一个开放元素堆栈。这个堆栈用于纠正嵌套错误和标签未关闭错误。这个算法也用状态机描述,它的状态叫做"insertion modes"。

    让我们看看下面输入的树构建过程:

    1. <html>  
    2.     <body>  
    3.         Hello world   
    4.     body>  
    5.  html>  

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

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

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

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

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

    图 10: 示例HTML树的构建

  • 相关阅读:
    Can't remove netstandard folder from output path (.net standard)
    website项目的reference问题
    The type exists in both DLLs
    git常用配置
    Map dependencies with code maps
    How to check HTML version of any website
    Bootstrap UI 编辑器
    网上职位要求对照
    Use of implicitly declared global variable
    ResolveUrl in external JavaScript file in asp.net project
  • 原文地址:https://www.cnblogs.com/fxie/p/2862759.html
Copyright © 2011-2022 走看看