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"?>8123100601102371810002CMB621483038515648721560166487200';
$s = simplexml_load_string($xml_str);
var_dump($s);
echo "---------\n";
$xml_str = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>8123100601102371810002CMB6214830385156487215601664872CMB621483038515648721560166487200';
$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 解析器是不认的,并且还不报错。