Java 正则表达式 零宽断言获取XML字符串中某一属性和节点的值

14566402169849949.jpg

最近在做一个银行支付的需求,测试银行的支付反馈,银行通知回来的是一个xml格式的字符串,示例如下

<shopOrderService version='1.0'>
    <orderData id='63340519408918945280394799954349' shopTraceNo='7' success='00'>
        <submitTime>20160810142922</submitTime>
        <merchant id='002777982990003' />
        <transData type='020211'>
            <installments timing='3'></installments>
            <shopBatchNo>20101110</shopBatchNo>
            <remark>分期测试</remark>
            <addData>测试</addData>
            <transAmount>200000</transAmount>
            <totalAmount currency='156'>200000</totalAmount>
            <hbAmount>0</hbAmount>
            <returnCode>00</returnCode>
            <returnMessage>支付成功</returnMessage>
            <authCode>737722</authCode>
            <traceNo>757798</traceNo>
            <batchNo>881170</batchNo>
            <invoiceNo>757798</invoiceNo>
            <hostTransTime>20160810142922</hostTransTime>
        </transData>
        <pospOrderId>563620</pospOrderId>
        <card no='************2599'></card>
    </orderData>
</shopOrderService>

然后,众多的属性和节点中,每个订单返回的xml数据格式还不一定一致,但是肯定的是 id='63340519408918945280394799954349'属性 和

returnMessage 节点是一定能有返回值的,而恰好,我这里只需要取得这两个值就可以了

以往的经验刚开始的第一思路都是要解析xml方式获取这两个值,判断属性是不是id,判断节点是不是returnMessage,等,然后在想了想我只需要获取以上两个值就可以了,使用xml方式是不是有点太繁琐,而且效率也不高。干脆直接使用正则表达式来匹配算了,正好最近使用正则表达式中的零宽断言,我想肯定会搞出来的!

首先我的第一版是这样的

String content = "<shopOrderService version='1.0'><orderData id='63340519408918945280394799954349' shopTraceNo='7' success='00'><submitTime>20160810142922</submitTime><merchant id='002777982990003' /><transData type='020211'><installments timing='3'></installments><shopBatchNo>20101110</shopBatchNo><remark>分期测试</remark><addData>测试</addData><transAmount>200000</transAmount><totalAmount currency='156'>200000</totalAmount><hbAmount>0</hbAmount><returnCode>00</returnCode><returnMessage>支付成功</returnMessage><authCode>737722</authCode><traceNo>757798</traceNo><batchNo>881170</batchNo><invoiceNo>757798</invoiceNo><hostTransTime>20160810142922</hostTransTime></transData><pospOrderId>563620</pospOrderId><card no='************2599'></card></orderData></shopOrderService>";
// 匹配订单号
Pattern pattern = Pattern.compile("(?<=id=\')\\d{32}+");  
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
	System.out.println("订单号:"+matcher.group());
}
// 匹配状态码
Pattern pattern2 = Pattern.compile("(?<=<returnMessage>)([^<])+");  
Matcher matcher2 = pattern2.matcher(content);
while(matcher2.find()){
	System.out.println("状态:"+matcher2.group());
}

结果:
订单号:63340519408918945280394799954349
状态:支付成功

搞定,就是这么soeasy,上面正则用到了零宽断言语法,不明白的在站点搜索关键字:零宽断言

但是感觉还是不够美观,有点强迫症的我,就像,两个需求能不能用一条正则表达式来写,这样,我就可以用一个while循环遍历我需要的结果,这么做不是可以做到代码优化了么?,说干就干

第二个版本代码如下

Pattern pattern = Pattern.compile("((?<=id=\')\\d{32}+|(?<=<returnMessage>)([^<])+)");  
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
	System.out.println(matcher.group());
}

结果:
订单号:63340519408918945280394799954349
状态:支付成功

这段正则中使用了 | 表达式,表示或,(正则A | 正则B)

是不是代码一下子变得简洁了许多,然而,这就完了,怎么可能,仔细想想,如果上面的xml中不是一个id匹配,或不是一个returnMessage匹配,那上吗的代码匹配出来的结果,可就不一定正确了,很有可能你匹配的前几行都是id也不一定。所以第三版代码就行了正确优化

Pattern pattern = Pattern.compile("((?<id>(?<=id=\')\\d{32}+)|(?<return>(?<=<returnMessage>)([^<])+))");  
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
	if (matcher.group("id") != null) {
		System.out.println(matcher.group("id"));
	}
	if (matcher.group("return") != null) {
		System.out.println(matcher.group("return"));
	}
}

结果:
订单号:63340519408918945280394799954349
状态:支付成功

这样看起来,就放心多了。

第三版中使用了,java中matcher.group(string name)的语法,不明白的可以看看我的上一篇文章《Java 正则表达式 Pattern类与Matcher类详解》 关于零宽断言的其他用途,可以在站点中搜索关键字: 零宽断言

未经允许请勿转载:程序喵 » Java 正则表达式 零宽断言获取XML字符串中某一属性和节点的值

点  赞 (0) 打  赏
分享到: