截取xm特定l标签中内容的正则_拿尤大大写的正则表达式处理一个业务上的问题...

在一次crud的时候,碰到了这样一个接口返回的数据是这样子的

<MachineModel machModelId="915432156" machModelName="故障标准传动链" machLayoutStatus="0">
 <item machModelId="915432156" itemtype="7" id="915432156_1" name="行星" bearingType="SRB/CARB" bearingCompany="FAG" ftf="0.455" bsf="10.718" bpfo="13.64" bpfi="16.36" position_x="127" position_y="150" speedRate="0.008350566967190259" left="8" right="16">
    item>
 <item machModelId="915432156" itemtype="7" id="915432156_2" name="恒星" bearingType="F-573602.NCF-WPOS" bearingCompany="FAG" ftf="0.476" bsf="20.7" bpfo="30.9" bpfi="34.1" position_x="287" position_y="150" speedRate="0.008350566967190259" left="16" right="3">
    item>
MachineModel>
f87f9228295c0d4f6158e9a2e394a351.png

后端将xml配置文件读出来返回给我了,要我拿到标签上的数据在页面上的位置做展示。嗯?

暂时没什么好的想法, 那么就直接innerHtml然后document.getElementsByTagName吧。

507c17d2e877f5b994dd987789fe2237.png

写完了之后,发现可维护性太差了吧。写的确实有些辣眼睛,想到是不是可以把vue的模板解析的代码借鉴(抄一抄)下,解析模板字符串,拿到标签上的数据。

正则
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`; // aaa-bbb  // 命名空间
const qnameCapture = `((?:${ncname}\\:)?${ncname})`; //   ?: 代表匹配不捕获
const startTagOpen = new RegExp(`^<${qnameCapture}`); // 标签开头的正则 捕获的内容是标签名
const endTag = new RegExp(`^${qnameCapture}[^>]*>`); // 匹配标签结尾的 
const attribute =  /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/;  // 匹配属性的 const startTagClose =  /^\s*(\/?)>/;  // 匹配标签结束的 >  也能是自闭合标签,所以 />
创建parseHtml函数,通过闭包的形式创建辅助函数公用html模板字符串参数。循环html字符串,处理不同的情况,处理之后进行截取。
 while (html) {
     let textEnd = html.indexOf(')// 判断是否是if (textEnd === 0) {// 如果进来了,那么这可能是开始标签也可能是结束标签let startTagMatch = parseStartTag(html) // 对开始标签进行解析 
, 返回处理后的结果,主要数据为tagNameif (startTagMatch) {// 进栈
             start(startTagMatch.tagName)// 如果匹配到了自闭和标签if (startTagMatch.autoEnd) {
                 end(startTags[startTags.length - 1])
             }continue // 如果开始标签匹配完毕后,继续下一次匹配
         }// 尝试匹配结束标签let endTagMatch = html.match(endTag)if (endTagMatch) {
             advance(endTagMatch[0].length)
             end(endTagMatch[1])continue
         }
     }let text// 如果大于0,则说明距离下一个开始标签还有距离, 而且中间值是文本
111222
if (textEnd >= 0) {
         text = html.substring(0, textEnd)
         advance(text.length)// 这里去除字符串即可,无需进行额外处理
     }
 }
最核心的函数解析开始标签,拿到需要的属性
function parseStartTag() {
    let start = html.match(startTagOpen)
    if (start) {
        const match = {
            tagName: start[1], // 匹配到第一个分组, 在这里就是这个标签名。
            attrs: []
        }
        advance(start[0].length) // start[0] 代表匹配到的结果

        let endT, attr;
        // 如果没有匹配到结束标签并且还能匹配到属性的话那么就开始解析属性
        while (!(endT = html.match(startTagClose)) && (attr = html.match(attribute))) {
            advance(attr[0].length) // 将属性去掉
            match.attrs.push({
                name: attr[1],
                value: attr[3] || attr[4] || attr[5]
            })
        }
        stack.push({ tagName: match.tagName, attrs: match.attrs })
        // 这里处理了自闭和标签
        if (endT[0].trim() === '/>' && html.trim().match(startTagClose)) {
            let endTagMatch = html.match(startTagClose)
            if (endTagMatch) {
                advance(endTagMatch[0].length)
            }
            return { ...match, autoEnd: true }
        } else {
            advance(endT[0].length) // 将开始标签的> 去掉
            return match
        }
    }
}
匹配到开始标签,需要进栈
 function start(tagName) {
     startTags.push(tagName)
 }
匹配到结束标签,需要进栈,   开始与结束标签进栈的目的是对匹配到的结束标签是否是上一次匹配到的开始标签,否则就报错。至于自闭合标签在parseStartTag函数中处理过了。
function end(tagName) {
    endTags.push(tagName)
    if (tagName === startTags[startTags.length - 1]) {
        startTags.splice(-1)
    } else {
        console.error('开始标签与结束标签不匹配')
        // 进行异常处理
    }
}
对html字符串进行截取
 function advance(n) {
     html = html.substring(n)
 }
完整代码
215e514be18e02b14f78c25627026503.png
返回的处理结果
c244275e0586ac1361e2c9e7a7fd765e.png

谢谢看完

如果这篇文章对您有所帮助的话,那就点个赞趴。

往期文章:

【我只看到了第三层】重新聊聊webpack

通俗易懂的实现符合promise A+ 规范的自定义promise

js异步编程,eventLoop、消息队列都是做什么的?什么是宏任务,什么是微任务

webpack4 搭建企业级脚手架

关注公众号查看更多有趣的文章、干货和完整代码。

f7af9e6a2cbe118c725defd47f76da48.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值