乐趣区

关于前端:关于字符串解析的一点理解-以解析一段HTML字符串为例

在剖析一段字符串的时候,能够借助字符串的 indexOf 等办法,或者是正则表达式,可是,如果须要解析的是上面这段字符串:

<group>
    <arc c-bind:cx='_width*0.5' c-bind:cy='_height*0.5' c-bind:radius1='_min*0.5' radius2='100' deg='120deg'>
    </arc>
    <group c-for='value in dataList'>
        <circle c-bind:cx='value' c-on:click='doit0' c-bind:cy='value' radius='10'></circle>
        <text c-bind:x='value+20' c-bind:y='value' c-bind:content='value' fill-color='red'></text>
    </group>
    <path>
        <move-to x='10' y='10'></move-to>
        <line-to x='100' y='100'></line-to>
    </path>
    <text c-bind:x='_width*0.5' c-bind:y='_height*0.5'> 文字 </text>
</group>

什么时候可能会须要解析相似这样的字符串?比方你可能心愿的 nodejs 环境开发一个爬虫,剖析爬到的页面内容,或者是像下面的设计,用 html 来表白心愿绘制什么样的图形后通过 js 在 canvas 画布上绘制出用户的用意等。

上面,咱们来一起看看,具体的怎么一步步剖析解决下面的字符串蕴含的信息的。

咱们把剖析分为这几个步骤:剖析出符号 → 剖析出单词 → 单词信息剖析 → 获取整体信息

## 剖析出符号

咱们把一个最小的相似 ” 语句 ” 的称为单词(和编译原理中的单词加以辨别),比方这里的一个标签,而为了失去单词,首先须要剖析的称为符号。比方对 “<div> 你好 </div>” 而言,就存在三个符号:“<div>”、” 你好 ” 和 ”</div>”。

因而,符号就是容易剖析出且在此基础上很容易剖析出单词的存在,具体什么是符号,取决于剖析的内容和指标。

下面的内容,剖析出符号的最终后果就是:

比方第二个符号,原始代码是 ”<arc c-bind:cx=’_width*0.5′ c-bind:cy=’_height*0.5′ c-bind:radius1=’_min*0.5′ radius2=’100′ deg=’120deg’>”,通过剖析失去,他是一个标签的开始局部,名称叫 arc,有一些属性等。

那么,这样的符号是如何剖析进去的?很简略,通过 while 循环即可。

在剖析一个符号开始前,如果遇到的第一个非空白字符是 ”<“,阐明这是一个标签(可能是开始、完结或自闭合的),直到遇到 ”>” 的时候,剖析完结,也就是获取了一个符号。

而如果在剖析一个符号开始前,遇到的第一个非空白字符不是 ”<“,阐明这是一段文本,等遇到 ”<“ 的时候,回退一步即可取得一段文本符号。

而对于标签符号,只有在剖析的时候额定加些判断,就能够获取更丰盛的信息并获取属性值等。从而,就失去了下面的符号列表。

## 剖析出单词

在下面符号列表的根底上,咱们接下来将剖析出上面的单词列表:

很显著,单词显著比符号要少。那么,如何通过符号列表获取单词列表?这会比上一步容易的多。

首先,你读取了符号列表的第一个符号,如果是文本或者自闭合标签,就曾经获取了第一个单词,否则,肯定是开始标签。

当初,你把这个开始标签寄存到栈(先进后出)中去,并占据单词列表的一个地位,接着察看下一个符号,如果是文本或者自闭合标签,就是一个新的单词,否则查看是否是开始标签,如果是,同样的解决,否则,判断是否和以后栈顶的元素匹配,如果匹配,出栈并实现了一个单词的匹配,不然就抛出谬误。

如此重复上来,直到符号列表遍历结束,察看此时的栈,如果还有元素,能够默认自闭合即可。

## 单词信息剖析

在上一步,除了剖析出单词外,还须要额定给每个单词标记档次(例如:根 group 是第一层,根的孩子是第二层,以此类推)。

档次是如何获取的?比方,你以后的档次是 deep,如果遇到的下一个符号是开始符号,那么,下一个单词(或文本,下同)的档次就一个是 deep+1,如果遇到的是完结符号,下一个单词就应该是 deep-1,否则就仍旧是 deep。

获取整体信息

对于一个字符串表达式而言,就是求值,对于 json 字符串而言,就是获取 json 对象,而在此处,就是要获取一个带有关系的 DOM 树。

先看看最终的后果:

咱们拿节点 ”<circle c-bind:cx=’value’ c-on:click=’doit0′ c-bind:cy=’value’ radius=’10’></circle>” 举例子。

通过 parentNode 和 childNodes 指明了它的父节点是第二个节点 group,没有孩子,前一个兄弟 preNode 为 null 没有,后一个兄弟 nextNode 为 4,也就是 text 标签。

同样的,咱们来说说思路。

在单词列表中,拿出一个单词(其实也就是节点或文本节点),如果下一个单词的 deep 和以后的一样,就是兄弟关系,如果小一级,就是以后结点的孩子,这都比拟容易。

如果比以后结点的 deep 大,怎么办?阐明以后这个节点是叶子,须要回溯,回溯到 deep 和新的节点 deep 一样的即可,那么新的节点就是此节点的下一个兄弟,以此类推即可。

小结

上述对于解析字符串 html 的算法,曾经封装并对外开源:解析 xhtml 为 json 对象

退出移动版