解析HTML字符串成AST树
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树的更多相关文章
- js字符串解析与转换成数字
解析允许字符串中含有非法数字字符,解析按从左至右的顺序,如果遇到非数字字符就停止.而转换不允许出现非数字字符,否则会失败并返回NaN
- dom4j解析xml字符串实例
DOM4J 与利用DOM.SAX.JAXP机制来解析xml相比,DOM4J 表现更优秀,具有性能优异.功能强大和极端易用使用的特点,只要懂得DOM基本概念,就可以通过dom4j的api文档来解析xml ...
- C#解析JSON字符串总结
JSON文件读取到内存中就是字符串,.NET操作JSON就是生成与解析JSON字符串. 操作JSON通常有以下几种方式: 1. 原始方式:按照JSON字符串自己来解析. 2. 通用方式[★★★★★]: ...
- Json转model对象,model转json,解析json字符串
GitHub链接: https://github.com/mozhenhau/D3Json D3Json 通过swift的反射特性,把json数据转换为model对象,本类最主要是解决了其他一般jso ...
- C#解析JSON字符串总结(转载)
JSON文件读取到内存中就是字符串,.NET操作JSON就是生成与解析JSON字符串. 操作JSON通常有以下几种方式: 1. 原始方式:按照JSON字符串自己来解析. 2. 通用方式[★★★★★]: ...
- java解析Json字符串之懒人大法
面对Java解析Json字符串的需求,有很多开源工具供我们选择,如google的Gson.阿里巴巴的fastJson.在网上能找到大量的文章讲解这些工具的使用方法.我也是参考这些文章封装了自己的Jso ...
- 一、JSON解析与字符串化
JSON.stringify() 序列化对象.数组或原始值 语法:JSON.stringify(o,filter,indent) o,要转换成JSON的对象.数组或原始值 filter,指定要序列化的 ...
- Atitit.注解and属性解析(2)---------语法分析 生成AST attilax总结 java .net
Atitit.注解and属性解析(2)---------语法分析 生成AST attilax总结 java .net 1. 应用场景:::因为要使用ui化的注解 1 2. 使用解释器方式来实现生成 ...
- JackSon解析json字符串
JackSon解析json字符串 原文:http://blog.csdn.net/java_huashan/article/details/9353903 概述 jackson解析json例子 准备工 ...
- java解析xml字符串(用dom4j)
package com.smsServer.Dhst; import java.util.HashMap; import java.util.Iterator; import java.util.Ma ...
随机推荐
- Angular Material 18+ 高级教程 – CDK Portal
前言 CDK Portal 是 Angular Material 对 Angular Dynamic Component (ViewContainerRef,TemplateRef,createCom ...
- Email 关于 POP3 IMAP SMTP office365 Outlook Gmail G-Suit shared mailbox小小理解
Outlook 是微软的一个 email 软件, 管理 email 的 UI. Gmail 是 google 的 office365 是一个配套, 里面有 email, one drive, exce ...
- 10款好用的开源 HarmonyOS 工具库
大家好,我是 V 哥,今天给大家分享10款好用的 HarmonyOS的工具库,在开发鸿蒙应用时可以用下,好用的工具可以简化代码,让你写出优雅的应用来.废话不多说,马上开整. 1. efTool efT ...
- Linux如何使用trim命令保持SSD的读写速度
随着硬盘技术的不断发展何固态硬盘的大量使用,你肯定听说过或者使用过固态硬盘,固态硬盘(或固态硬盘)能够达到比传统硬盘更快的读取和写入数据的速度,您可能不知道的是,随着时间的推移,当磁盘写满时,SSD硬 ...
- iOS中搜索框EVNCustomSearchBar使用小结
最近在项目开发中用到了搜索框,之前都是用的系统的searchbar,现有项目中用的是EVNCustomSearchBar,我试了一下还挺方便,下面说一下具体的用法. 第一步:引入添加相关的委托代理EV ...
- 在C#中基于Semantic Kernel的检索增强生成(RAG)实践
Semantic Kernel简介 玩过大语言模型(LLM)的都知道OpenAI,然后微软Azure也提供了OpenAI的服务:Azure OpenAI,只需要申请到API Key,就可以使用这些AI ...
- 下一代云电脑技术来临,为什么PC Farm才是未来,以ToDesk为例
近年来飞速发展的云电脑技术,正在挤压传统电脑的生存空间.由于用户对电脑计算能力的要求日益增高,而传统电脑往往会受限于硬件性能无法更新,更换花费较高等因素,难以满足用户对高性能电脑的期待. 与此同时,下 ...
- 哈希表(C语言实现)
在计算机世界中,哈希表如同一位聪慧的图书管理员.他知道如何计算索书号,从而可以快速找到目标图书. 文章目录 1.哈希表的概念 1.1哈希表的基本操作 1.2哈希表的常用操作 2.基于数实现哈希表 2. ...
- 多模型COE方法
1.概述 在当前的人工智能发展中,单一模型的表现往往难以满足复杂任务的需求.为应对这些挑战,多模型协作的方法应运而生,"专家组合"(Mixture of Experts)便是其中一 ...
- mac 搭建 paho.mqtt.cpp 二次开发环境搭建
mac 搭建 c mqtt 二次开发环境搭建 参考教程 # 下载源码 git clone https://github.com/eclipse/paho.mqtt.c.git # 使用make 编译 ...