ArrayXML.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: tandunzhao
  5. * Date: 2017/12/13
  6. * Time: 下午2:54
  7. */
  8. namespace App\Libs\allinpay;
  9. use XMLReader;
  10. use DOMDocument;
  11. use Exception;
  12. class ArrayXML
  13. {
  14. protected $bOptimize = FALSE;
  15. public $bFormatted = FALSE;
  16. public function parseString( $sXml , $bOptimize = FALSE) {
  17. $oXml = new XMLReader();
  18. $this -> bOptimize = (bool) $bOptimize;
  19. try {
  20. // Set String Containing XML data
  21. $oXml->XML($sXml);
  22. // Parse Xml and return result
  23. return $this->parseXml($oXml);
  24. } catch (Exception $e) {
  25. echo $e->getMessage();
  26. }
  27. }
  28. public function parseFile( $sXmlFilePath , $bOptimize = false ) {
  29. $oXml = new XMLReader();
  30. $this -> bOptimize = (bool) $bOptimize;
  31. try {
  32. // Open XML file
  33. $oXml->open($sXmlFilePath);
  34. // Parse Xml and return result
  35. return $this->parseXml($oXml);
  36. } catch (Exception $e) {
  37. echo $e->getMessage(). ' | Try open file: '.$sXmlFilePath;
  38. }
  39. }
  40. protected function parseXml( XMLReader $oXml ) {
  41. $aAssocXML = null;
  42. $iDc = -1;
  43. while($oXml->read()){
  44. switch ($oXml->nodeType) {
  45. case XMLReader::END_ELEMENT:
  46. if ($this->bOptimize) {
  47. $this->optXml($aAssocXML);
  48. }
  49. return $aAssocXML;
  50. case XMLReader::ELEMENT:
  51. if(!isset($aAssocXML[$oXml->name])) {
  52. if($oXml->hasAttributes) {
  53. $aAssocXML[$oXml->name][] = $oXml->isEmptyElement ? '' : $this->parseXML($oXml);
  54. } else {
  55. if($oXml->isEmptyElement) {
  56. $aAssocXML[$oXml->name] = '';
  57. } else {
  58. $aAssocXML[$oXml->name] = $this->parseXML($oXml);
  59. }
  60. }
  61. } elseif (is_array($aAssocXML[$oXml->name])) {
  62. if (!isset($aAssocXML[$oXml->name][0]))
  63. {
  64. $temp = $aAssocXML[$oXml->name];
  65. foreach ($temp as $sKey=>$sValue)
  66. unset($aAssocXML[$oXml->name][$sKey]);
  67. $aAssocXML[$oXml->name][] = $temp;
  68. }
  69. if($oXml->hasAttributes) {
  70. $aAssocXML[$oXml->name][] = $oXml->isEmptyElement ? '' : $this->parseXML($oXml);
  71. } else {
  72. if($oXml->isEmptyElement) {
  73. $aAssocXML[$oXml->name][] = '';
  74. } else {
  75. $aAssocXML[$oXml->name][] = $this->parseXML($oXml);
  76. }
  77. }
  78. } else {
  79. $mOldVar = $aAssocXML[$oXml->name];
  80. $aAssocXML[$oXml->name] = array($mOldVar);
  81. if($oXml->hasAttributes) {
  82. $aAssocXML[$oXml->name][] = $oXml->isEmptyElement ? '' : $this->parseXML($oXml);
  83. } else {
  84. if($oXml->isEmptyElement) {
  85. $aAssocXML[$oXml->name][] = '';
  86. } else {
  87. $aAssocXML[$oXml->name][] = $this->parseXML($oXml);
  88. }
  89. }
  90. }
  91. if($oXml->hasAttributes) {
  92. $mElement =& $aAssocXML[$oXml->name][count($aAssocXML[$oXml->name]) - 1];
  93. while($oXml->moveToNextAttribute()) {
  94. $mElement[$oXml->name] = $oXml->value;
  95. }
  96. }
  97. break;
  98. case XMLReader::TEXT:
  99. case XMLReader::CDATA:
  100. $aAssocXML[++$iDc] = $oXml->value;
  101. }
  102. }
  103. return $aAssocXML;
  104. }
  105. public function optXml(&$mData) {
  106. if (is_array($mData)) {
  107. if (isset($mData[0]) && count($mData) == 1 ) {
  108. $mData = $mData[0];
  109. if (is_array($mData)) {
  110. foreach ($mData as &$aSub) {
  111. $this->optXml($aSub);
  112. }
  113. }
  114. } else {
  115. foreach ($mData as &$aSub) {
  116. $this->optXml($aSub);
  117. }
  118. }
  119. }
  120. }
  121. public function fixCDATA($string) {
  122. //fix CDATA tags
  123. $find[] = '&lt;![CDATA[';
  124. $replace[] = '<![CDATA[';
  125. $find[] = ']]&gt;';
  126. $replace[] = ']]>';
  127. $string = str_ireplace($find, $replace, $string);
  128. return $string;
  129. }
  130. public function is_assoc( $array ) {
  131. return (is_array($array) && 0 !== count(array_diff_key($array, array_keys(array_keys($array)))));
  132. }
  133. public function toXml($data, $rootNodeName = 'data', &$xml=null)
  134. {
  135. // turn off compatibility mode as simple xml throws a wobbly if you don't.
  136. if ( ini_get('zend.ze1_compatibility_mode') == 1 ) ini_set ( 'zend.ze1_compatibility_mode', 0 );
  137. if ( is_null( $xml ) ) {
  138. $xml = simplexml_load_string(stripslashes("<?xml version='1.0' encoding='UTF-8'?><$rootNodeName></$rootNodeName>"));
  139. }
  140. // loop through the data passed in.
  141. foreach( $data as $key => $value ) {
  142. // no numeric keys in our xml please!
  143. $numeric = false;
  144. if ( is_numeric( $key ) ) {
  145. $numeric = 1;
  146. $key = $rootNodeName;
  147. }
  148. // delete any char not allowed in XML element names
  149. $key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key);
  150. //check to see if there should be an attribute added (expecting to see _id_)
  151. $attrs = false;
  152. //if there are attributes in the array (denoted by attr_**) then add as XML attributes
  153. if ( is_array( $value ) ) {
  154. foreach($value as $i => $v ) {
  155. $attr_start = false;
  156. $attr_start = stripos($i, 'attr_');
  157. if ($attr_start === 0) {
  158. $attrs[substr($i, 5)] = $v; unset($value[$i]);
  159. }
  160. }
  161. }
  162. // if there is another array found recursively call this function
  163. if ( is_array( $value ) ) {
  164. if ( $this->is_assoc( $value ) || $numeric ) {
  165. // older SimpleXMLElement Libraries do not have the addChild Method
  166. if (method_exists('SimpleXMLElement','addChild')) {
  167. $node = $xml->addChild( $key, null);
  168. if ($attrs) {
  169. foreach($attrs as $key => $attribute) {
  170. $node->addAttribute($key, $attribute);
  171. }
  172. }
  173. }
  174. }else{
  175. $node =$xml;
  176. }
  177. // recrusive call.
  178. if ( $numeric ) $key = 'anon';
  179. $this->toXml( $value, $key, $node );
  180. } else {
  181. // older SimplXMLElement Libraries do not have the addChild Method
  182. if (method_exists('SimpleXMLElement','addChild')) {
  183. $childnode = $xml->addChild( $key, $value);
  184. if ($attrs) {
  185. foreach($attrs as $key => $attribute) {
  186. $childnode->addAttribute($key, $attribute);
  187. }
  188. }
  189. }
  190. }
  191. }
  192. if ($this->bFormatted) {
  193. // if you want the XML to be formatted, use the below instead to return the XML
  194. $doc = new DOMDocument('1.0');
  195. $doc->preserveWhiteSpace = false;
  196. @$doc->loadXML( $this->fixCDATA($xml->asXML()) );
  197. $doc->formatOutput = true;
  198. return $doc->saveXML();
  199. }
  200. // pass back as unformatted XML
  201. return $xml->asXML();
  202. }
  203. public function toXmlGBK($data, $rootNodeName = 'data', &$xml=null)
  204. {
  205. $xml = str_replace('<?xml version="1.0" encoding="UTF-8"?>', '<?xml version="1.0" encoding="GBK"?>', $this->toXml($data, $rootNodeName, $xml));
  206. // dd($xml);
  207. return mb_convert_encoding($xml, 'GBK', 'UTF-8');
  208. }
  209. }