去年中旬的时候做过一个和第三方支付交互的XML报文交互接口, 规格是第三方支付定的, 比较全面, 涉及到完整性检查, 身份验证, 我还加上了XSD格式验证. 最近在做一个内部的报文交互接口, 发现了一些问题, 简单阐述一下, 算是一个小的总结.
先说说XML报文的实现, 最简单的莫过于直接拼字符串, 我接手前的同事也是这么做的, 如下:
$str = '<?xml version="1.0" encoding="utf-8"?>';
$str .= '<MbfService>';
$str .= '<input1>';
这样做本身没有什么问题, 问题在于里边有一块结构体是特异化的,就是说它是跟着业务走的,不同的业务接口会有不同的结构体定义,
$str .= $this->xmlbody($body);
private function xmlbody($body){
$str = '';
if(is_array($body)){
foreach($body as $key=>$value){
if(is_int($key)){
$str .= $this->xmlbody($value);
}else{
$str .= '<'.$key.'>'.$this->xmlbody($value).'</'.$key.'>';
}
}
}else{
$str .= $body;
}
$str = preg_replace("/([\x01-\x08\x0b-\x0c\x0e-\x1f])+/",' ',$str);
return $str;
原作者的想法是不想将底层代码开放出去, 不希望调用层直接传XML字符串进来拼接, 所以自作聪明地发明了传PHP数组进来, 然后再用自己编写的转换方法把这个数组解析为XML字符串进行拼接. 这个想法的确很有创造性, 我个人大概永远也想不出来. 但这个思路是错误的, 原因如下:
1 XML作为成熟的网络交互格式, 必然有很多官配的解析引擎,它们都是经过良好测试和设计的, 完全没必要自作聪明.
2 PHP数组结构简单, 索引值不能重复, 并不能完全模仿XML的树形数据结构 (比如同名的若干个element, 你如何用数组来表示?)
3 XML有几个陷阱, 比如XML的自定义字符, 在解析时候需要进行转义, 否则不能正确解析, 这些自己编写的解析器都可能埋下隐患.
4 用数组和自解析什么的保证XML格式正确什么的完全就是愚蠢和无知的, 只能说明他完全不知道XSD是什么.
很多程序员对XML并不了解, 或者说他们的了解仅仅停留在XML是一种标记结构这个层面上. 更深层次的为什么我们用XML以及XML的衍生技术直至甚少.还记得我去年做开发的时候, 我跟我经理说我需要几天熟悉一下XML,他跟我说这个也要花时间去看么?
回归正题, 我理想的XML报文交互应该是
1 交互一方首先定义好XSD, 无论是发送方和接收方都需要用这个XSD来检验报文格式的正确性.
2 接收方用XML引擎解析报文, 生成本地的业务模型进行后续处理
3 发送方如果发送的报文很简单, 可以直接拼接字符串, 但一般还是需要利用DOM模型来生成XML, 因为一般的业务都牵扯多层调用, 或者上边说到的对客户端程序员的部分实现屏蔽.
$MbfBody->appendChild ( $body );
$this->xml->formatOutput = $isFormatOut;
return $this->xml->saveXML ();
后续:
就在刚刚, 被接口定义方又坑了一把, 文档里写的XML格式描述不准确... 无奈之余也只能再次吐槽, 能不能用XSD来定义XML报文格式!