在剖析一段字符串的时候,能够借助字符串的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对象