如何构建DOM树-语法分析

什么是语法分析

语法分析:分析单词序列是否符合语法规则,并构建出由输入单词组成的数据结构(语法树)。
浏览器请求回来的HTML文档字符流, 经过词法分析得到了token序列。语法分析会对token序列进行语法检查,并构建成浏览器可以理解的数据结构-DOM树

HTML的DOM结构

根据DOM标准(程序访问HTML文档的标准),HTML文档是由节点构成的,节点之间拥有层级关系并构成了一颗节点树
节点可分为元素节点文本节点两大类。

<html>
  <head>
    <title>文档标题</title>
  </head>
  <body>
    <a href="www.baidu.com">我的链接</a>
    <h1>我的标题</h1>
  </body>
</html>

上面HTML文档对应的DOM树如下:
img
从上图可以看到,文本节点是当前元素节点的子节点。

为什么需要语法分析

程序 = 数据结构 + 算法。
HTML文档字符流经过词法解析和语法分析,构建成一颗DOM树。这样浏览器才能访问和操作HTML文档。

怎么实现语法分析

栈结构

HTML词法解析是按顺序解析字符流的,第一个开始标签对应的结束标签应该是最后出现的。为了匹配开始标签和结束标签,DOM树的构建可以使用栈结构来处理。
第一步,我们先定义元素节点文本节点两者的数据结构。

// 元素节点
function Element(){
    this.type = 'Element';
    this.open;            // 开始标签, 比如 <div id="1">
    this.name;            // 标签名称, 全部转换为小写
    this.close;           // 结束标签, 比如 </div>
    this.attributes = []; // 标签属性
    this.childNodes = []; // 子节点
}
// 文本节点
function Text(value){
    this.type = 'Text';
    this.value = value;
}

第二步,定义一个parse()函数来接收HTML词法解析得到的token列表,并用一个栈来存储处理过程中的节点。

function HTMLSyntaticalParser(){
    var stack = [new HTMLDocument];
    this.parse = function(token) {
        // 1.栈顶就是当前节点
        let curNode = stack[stack.length-1];
        let node = buildElement(token);
        switch(token.type){
            case 'StartTag':
                // 2.遇到开始标签就入栈,当前节点就是这个节点的父节点;
                curNode.childNodes.push(node);
                stack.push(node);
                break;
            case 'EndTag':
                // 3.遇到结束标签就出栈;
                stack.pop();
                break;
            case 'Text':
                // 4.遇到文本节点,如果当前节点是文本节点,则跟文本节点合并,
                // 否则入栈成为当前节点的子节点;
                if('Element' == curNode.type){
                    curNode.childNodes.push(node);
                    stack.push(node);
                } else if('Text' == curNode.type){
                    curNode.value += node.value;
                }
         }
    }
    this.getOutput = function(){
        // 5.构建过程中,遇到开始标签就入栈,遇到结束标签就出栈,最终栈顶就是根节点。
        return stack[0];
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值