1. 如何将一个字符传转换成一个AST树结构。

直接上代码:

 

const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`
const qnameCapture = `((?:${ncname}\\:)?${ncname})`
// 匹配 <div
const startTagOpen = new RegExp(`^<${qnameCapture}`)
// 匹配 > />
const startTagClose = /^\s*(\/?)>/
// 匹配 </div>
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)
const doctype = /^<!DOCTYPE [^>]+>/i //注意树形的html 只能有一个根节点
function parseHtmlToAst(html){ let text,root,currentParent,stack=[]; while(html){
let textEnd=html.indexOf("<");
if(textEnd===0){
//查找开始tag
const startTagMatch=parseStartTag();
if(startTagMatch){
//生成AST树
start(startTagMatch.tagName,startTagMatch.attrs);
continue;
}
//查找结束标签
const endTagMatch=html.match(endTag);
if(endTagMatch){
advance(endTagMatch[0].length);
//构造ast树
end(endTagMatch[1]);
continue;
} }
//文本节点
if(textEnd>0){
text=html.substring(0,textEnd);
}
if(text){
//截取字符串
advance(text.length);
chars(text);
} }
//截些开始标记
function parseStartTag(){
const start=html.match(startTagOpen); let end,attr;
//找到开始标记
if(start){
const match={
tagName:start[1],
attrs:[]
} advance(start[0].length)
//配置属性
while(!(end=html.match(startTagClose)) && (attr=html.match(attribute))){ match.attrs.push({
name:attr[1],
value: attr[3] || attr[4] || attr[5]
})
advance(attr[0].length); }
//匹配结束字符 > 或 />
if(end){
advance(end[0].length);
return match;
}
} } //截取字符串
function advance (n) {
html = html.substring(n)
}
//构造AST树形
function start(tagName,attrs){
const element=createAstElement(tagName,attrs); if(!root){
root=element;
}
currentParent=element;
stack.push(element);
} //结束钩爪树形
function end(tagName){
const element=stack.pop();
currentParent=stack[stack.length-1];
if(currentParent){
element.parent=currentParent;
currentParent.children.push(element);
} }
//处理文本节点
function chars(text){
text=text.trim();
if(text.length>0){
currentParent.children.push({
type:3,
text
})
} } function createAstElement(tagName,attrs){
return {
tag: tagName,
type: 1,
children:[],
attrs,
parent }
}
return root; } let html=`<div id="app" style="color:red;width:200px">
你好:{{name}}
<span class="text" style="color:green">{{age}}
</span>
</div>
`; let root=parseHtmlToAst(html);
console.info(root)

代码的逻辑是:

对字符串的处理,从头开始处理,先找 < 开头的字符,如果找到则用 正则表达式查找 <div 的标签,找到后,截取 后面的字符串,然后循环查找 属性,直到 找到 > 或 />字符为止,找到让后截取后面的字符串。

中间用到了堆栈作为树节点作为串联。

2.构造结果

解析HTML字符串成AST树的更多相关文章

  1. js字符串解析与转换成数字

    解析允许字符串中含有非法数字字符,解析按从左至右的顺序,如果遇到非数字字符就停止.而转换不允许出现非数字字符,否则会失败并返回NaN

  2. dom4j解析xml字符串实例

    DOM4J 与利用DOM.SAX.JAXP机制来解析xml相比,DOM4J 表现更优秀,具有性能优异.功能强大和极端易用使用的特点,只要懂得DOM基本概念,就可以通过dom4j的api文档来解析xml ...

  3. C#解析JSON字符串总结

    JSON文件读取到内存中就是字符串,.NET操作JSON就是生成与解析JSON字符串. 操作JSON通常有以下几种方式: 1. 原始方式:按照JSON字符串自己来解析. 2. 通用方式[★★★★★]: ...

  4. Json转model对象,model转json,解析json字符串

    GitHub链接: https://github.com/mozhenhau/D3Json D3Json 通过swift的反射特性,把json数据转换为model对象,本类最主要是解决了其他一般jso ...

  5. C#解析JSON字符串总结(转载)

    JSON文件读取到内存中就是字符串,.NET操作JSON就是生成与解析JSON字符串. 操作JSON通常有以下几种方式: 1. 原始方式:按照JSON字符串自己来解析. 2. 通用方式[★★★★★]: ...

  6. java解析Json字符串之懒人大法

    面对Java解析Json字符串的需求,有很多开源工具供我们选择,如google的Gson.阿里巴巴的fastJson.在网上能找到大量的文章讲解这些工具的使用方法.我也是参考这些文章封装了自己的Jso ...

  7. 一、JSON解析与字符串化

    JSON.stringify() 序列化对象.数组或原始值 语法:JSON.stringify(o,filter,indent) o,要转换成JSON的对象.数组或原始值 filter,指定要序列化的 ...

  8. Atitit.注解and属性解析(2)---------语法分析 生成AST attilax总结 java .net

    Atitit.注解and属性解析(2)---------语法分析 生成AST  attilax总结  java .net 1. 应用场景:::因为要使用ui化的注解 1 2. 使用解释器方式来实现生成 ...

  9. JackSon解析json字符串

    JackSon解析json字符串 原文:http://blog.csdn.net/java_huashan/article/details/9353903 概述 jackson解析json例子 准备工 ...

  10. java解析xml字符串(用dom4j)

    package com.smsServer.Dhst; import java.util.HashMap; import java.util.Iterator; import java.util.Ma ...

随机推荐

  1. 技术解析 | ZEGO 移动端超分辨率技术

    ​ 即构超分追求:速度更快.效果更好.码率更低.机型更广. 超分辨率(Super Resolution, SR)是从给定的低分辨率(Low Resolution, LR)图像中恢复高分辨率(High ...

  2. pytorch中LSTM各参数理解

    nn.LSTM(input_dim,hidden_dim,nums_layer,batch_first) 各参数理解: input_dim:输入的张量维度,表示自变量特征数 hidden_dim:输出 ...

  3. Kubernetes Deployment控制器(二十)

    前面我们学习了 ReplicaSet 控制器,了解到该控制器是用来维护集群中运行的 Pod 数量的,但是往往在实际操作的时候,我们反而不会去直接使用 RS,而是会使用更上层的控制器,比如我们今天要学习 ...

  4. 《Vue.js 设计与实现》读书笔记 - 第13章、异步组件与函数式组件

    第13章.异步组件与函数式组件 13.1 异步组件要解决的问题 用户可以简单通过 import 异步导入组件. <template> <component :is="asy ...

  5. 高通Perflock

    高通的Perflock是Qualcomm公司开发的一项技术,用于优化设备性能和功耗管理.Perflock是一种锁定机制,允许操作系统或应用程序在需要时对处理器的性能状态进行控制,从而确保在关键任务或高 ...

  6. AMBA总线架构简介

    于是乎,我们想到了总线,用一个统一的接口协议,设计出一个符合要求的总线,然后将ARM核和各种外设模块挂载在总线上,这样,命令和数据似乎便可以在CPU和外设之间自由穿梭. 1 AMBA总线 AMBA,英 ...

  7. vant2 List 组件 下拉加载 onLoad

    ps:loading finished onLoad 两个变量一个函数 : async onLoad() { console.log("onload"); // 异步更新数据 // ...

  8. Nuxt.js 应用中的 ready 事件钩子详解

    title: Nuxt.js 应用中的 ready 事件钩子详解 date: 2024/10/12 updated: 2024/10/12 author: cmdragon excerpt: read ...

  9. KubeSphere 社区双周报 | KubeKey v3.0.7 发布 | 2023-02-03

    KubeSphere 从诞生的第一天起便秉持着开源.开放的理念,并且以社区的方式成长,如今 KubeSphere 已经成为全球最受欢迎的开源容器平台之一.这些都离不开社区小伙伴的共同努力,你们为 Ku ...

  10. 重构案例:将纯HTML/JS项目迁移到Webpack

    我们已经了解了许多关于 Webpack 的知识,但要完全熟练掌握它并非易事.一个很好的学习方法是通过实际项目练习.当我们对 Webpack 的配置有了足够的理解后,就可以尝试重构一些项目.本次我选择了 ...