使用php函数simplexml_load_string解析xml注意事项技术
PHP 解析 xml 的方法有很多种,比如 DOMDocument 的 xpath,XMLReader,SimpleXML,XML Expat Parser 等。一般情况下,解析一段格式比较规则的 xml,程序员对字符的处理能力比较强的话,自己写一个解析器也未尝不可。大多数情况下,使用面向对象的库来解析 xml 是不太方便的,不如函数来的爽快。
使用函数 simplexml_load_string 的坑
文本讲述 PHP 函数 simplexml_load_string 解析 xml 的注意事项。对于提交比较小的 xml,使用此函数解析是再适合不过啦。关于此函数的坑,请看如下代码:
<?php $xml_str = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><MasMessage xmlns="http://www.99bill.com/mas_cnp_merchant_interface"><PciQueryContent><merchantId>812310060110237</merchantId><customerId>181</customerId><storablePan></storablePan><cardType>0002</cardType><pciInfos><pciInfo><bankId>CMB</bankId><storablePan>6214830385</storablePan><shortPhoneNo>1564872</shortPhoneNo><phoneNO>15601664872</phoneNO></pciInfo></pciInfos><responseCode>00</responseCode></PciQueryContent></MasMessage>'; $s = simplexml_load_string($xml_str); var_dump($s); echo "---------\n"; $xml_str = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><MasMessage xmlns="http://www.99bill.com/mas_cnp_merchant_interface"><PciQueryContent><merchantId>812310060110237</merchantId><customerId>181</customerId><storablePan></storablePan><cardType>0002</cardType><pciInfos><pciInfo><bankId>CMB</bankId><storablePan>6214830385</storablePan><shortPhoneNo>1564872</shortPhoneNo><phoneNO>15601664872</phoneNO></pciInfo><pciInfo><bankId>CMB</bankId><storablePan>6214830385</storablePan><shortPhoneNo>1564872</shortPhoneNo><phoneNO>15601664872</phoneNO></pciInfo></pciInfos><responseCode>00</responseCode></PciQueryContent></MasMessage>'; $s = simplexml_load_string($xml_str); var_dump($s); /** object(SimpleXMLElement)#5 (1) { ["PciQueryContent"]=> object(SimpleXMLElement)#7 (6) { ["merchantId"]=> string(15) "812310060110237" ["customerId"]=> string(3) "181" ["storablePan"]=> object(SimpleXMLElement)#8 (0) { } ["cardType"]=> string(4) "0002" ["pciInfos"]=> object(SimpleXMLElement)#9 (1) { ["pciInfo"]=> object(SimpleXMLElement)#10 (4) { ["bankId"]=> string(3) "CMB" ["storablePan"]=> string(10) "6214830385" ["shortPhoneNo"]=> string(7) "1564872" ["phoneNO"]=> string(11) "15601664872" } } ["responseCode"]=> string(2) "00" } } --------- object(SimpleXMLElement)#7 (1) { ["PciQueryContent"]=> object(SimpleXMLElement)#5 (6) { ["merchantId"]=> string(15) "812310060110237" ["customerId"]=> string(3) "181" ["storablePan"]=> object(SimpleXMLElement)#9 (0) { } ["cardType"]=> string(4) "0002" ["pciInfos"]=> object(SimpleXMLElement)#8 (1) { ["pciInfo"]=> array(2) { [0]=> object(SimpleXMLElement)#10 (4) { ["bankId"]=> string(3) "CMB" ["storablePan"]=> string(10) "6214830385" ["shortPhoneNo"]=> string(7) "1564872" ["phoneNO"]=> string(11) "15601664872" } [1]=> object(SimpleXMLElement)#11 (4) { ["bankId"]=> string(3) "CMB" ["storablePan"]=> string(10) "6214830385" ["shortPhoneNo"]=> string(7) "1564872" ["phoneNO"]=> string(11) "15601664872" } } } ["responseCode"]=> string(2) "00" } } */
解决方案示例
从上面的代码示例可以看出,pciInfos 下面的 pciInfo 有些情况下是对象,有些情况下是数组。这样就对后续处理的代码的写法增加了难度了。所以,写代码需要小心翼翼的。如下解决方法:
$infos = (array)$s->PciQueryContent->pciInfos; $cardsArr = (array)$infos; if (is_array($cardsArr['pciInfo'])) { $cardsArr = $cardsArr['pciInfo']; }
先将 pciInfos 转成数组,然后再通过 is_array 判断来获得多维卡信息数据,方便后续的遍历操作。
组装 xml 注意事项
另外,在组装 xml 数据时也需要格外小心,比如在标签的内容中出现 & 符号,这个对于正常人来讲,都认为是能被正常解析的,但是某些比较轴的 xml 解析器是不认的,并且还不报错。
暂无