/lib/php/PEAR/XMLParser.php

https://github.com/GunioRobot/Loggix · PHP · 261 lines · 132 code · 29 blank · 100 comment · 25 complexity · 451886a80229da3624ff74cf0a559af1 MD5 · raw file

  1. <?php
  2. /**
  3. * PEAR_XMLParser
  4. *
  5. * PHP versions 4 and 5
  6. *
  7. * @category pear
  8. * @package PEAR
  9. * @author Greg Beaver <cellog@php.net>
  10. * @author Stephan Schmidt (original XML_Unserializer code)
  11. * @copyright 1997-2009 The Authors
  12. * @license http://opensource.org/licenses/bsd-license New BSD License
  13. * @version CVS: $Id: XMLParser.php,v 1.22 2009/03/08 00:45:39 dufuz Exp $
  14. * @link http://pear.php.net/package/PEAR
  15. * @since File available since Release 1.4.0a1
  16. */
  17. /**
  18. * Parser for any xml file
  19. * @category pear
  20. * @package PEAR
  21. * @author Greg Beaver <cellog@php.net>
  22. * @author Stephan Schmidt (original XML_Unserializer code)
  23. * @copyright 1997-2009 The Authors
  24. * @license http://opensource.org/licenses/bsd-license New BSD License
  25. * @version Release: 1.8.0RC1
  26. * @link http://pear.php.net/package/PEAR
  27. * @since Class available since Release 1.4.0a1
  28. */
  29. class PEAR_XMLParser
  30. {
  31. /**
  32. * unserilialized data
  33. * @var string $_serializedData
  34. */
  35. var $_unserializedData = null;
  36. /**
  37. * name of the root tag
  38. * @var string $_root
  39. */
  40. var $_root = null;
  41. /**
  42. * stack for all data that is found
  43. * @var array $_dataStack
  44. */
  45. var $_dataStack = array();
  46. /**
  47. * stack for all values that are generated
  48. * @var array $_valStack
  49. */
  50. var $_valStack = array();
  51. /**
  52. * current tag depth
  53. * @var int $_depth
  54. */
  55. var $_depth = 0;
  56. /**
  57. * The XML encoding to use
  58. * @var string $encoding
  59. */
  60. var $encoding = 'ISO-8859-1';
  61. /**
  62. * @return array
  63. */
  64. function getData()
  65. {
  66. return $this->_unserializedData;
  67. }
  68. /**
  69. * @param string xml content
  70. * @return true|PEAR_Error
  71. */
  72. function parse($data)
  73. {
  74. if (!extension_loaded('xml')) {
  75. include_once 'PEAR.php';
  76. return PEAR::raiseError("XML Extension not found", 1);
  77. }
  78. $this->_valStack = array();
  79. $this->_dataStack = array();
  80. $this->_depth = 0;
  81. if (
  82. strpos($data, 'encoding="UTF-8"')
  83. || strpos($data, 'encoding="utf-8"')
  84. || strpos($data, "encoding='UTF-8'")
  85. || strpos($data, "encoding='utf-8'")
  86. ) {
  87. $this->encoding = 'UTF-8';
  88. }
  89. if (version_compare(phpversion(), '5.0.0', 'lt') && $this->encoding == 'UTF-8') {
  90. $data = utf8_decode($data);
  91. }
  92. $xp = xml_parser_create($this->encoding);
  93. xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0);
  94. xml_set_object($xp, $this);
  95. xml_set_element_handler($xp, 'startHandler', 'endHandler');
  96. xml_set_character_data_handler($xp, 'cdataHandler');
  97. if (!xml_parse($xp, $data)) {
  98. $msg = xml_error_string(xml_get_error_code($xp));
  99. $line = xml_get_current_line_number($xp);
  100. xml_parser_free($xp);
  101. include_once 'PEAR.php';
  102. return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2);
  103. }
  104. xml_parser_free($xp);
  105. return true;
  106. }
  107. /**
  108. * Start element handler for XML parser
  109. *
  110. * @access private
  111. * @param object $parser XML parser object
  112. * @param string $element XML element
  113. * @param array $attribs attributes of XML tag
  114. * @return void
  115. */
  116. function startHandler($parser, $element, $attribs)
  117. {
  118. $type = 'string';
  119. $this->_depth++;
  120. $this->_dataStack[$this->_depth] = null;
  121. $val = array(
  122. 'name' => $element,
  123. 'value' => null,
  124. 'type' => $type,
  125. 'childrenKeys' => array(),
  126. 'aggregKeys' => array()
  127. );
  128. if (count($attribs) > 0) {
  129. $val['children'] = array();
  130. $val['type'] = 'array';
  131. $val['children']['attribs'] = $attribs;
  132. }
  133. array_push($this->_valStack, $val);
  134. }
  135. /**
  136. * post-process data
  137. *
  138. * @param string $data
  139. * @param string $element element name
  140. */
  141. function postProcess($data, $element)
  142. {
  143. return trim($data);
  144. }
  145. /**
  146. * End element handler for XML parser
  147. *
  148. * @access private
  149. * @param object XML parser object
  150. * @param string
  151. * @return void
  152. */
  153. function endHandler($parser, $element)
  154. {
  155. $value = array_pop($this->_valStack);
  156. $data = $this->postProcess($this->_dataStack[$this->_depth], $element);
  157. // adjust type of the value
  158. switch(strtolower($value['type'])) {
  159. // unserialize an array
  160. case 'array':
  161. if ($data !== '') {
  162. $value['children']['_content'] = $data;
  163. }
  164. if (isset($value['children'])) {
  165. $value['value'] = $value['children'];
  166. } else {
  167. $value['value'] = array();
  168. }
  169. break;
  170. /*
  171. * unserialize a null value
  172. */
  173. case 'null':
  174. $data = null;
  175. break;
  176. /*
  177. * unserialize any scalar value
  178. */
  179. default:
  180. settype($data, $value['type']);
  181. $value['value'] = $data;
  182. break;
  183. }
  184. $parent = array_pop($this->_valStack);
  185. if ($parent === null) {
  186. $this->_unserializedData = &$value['value'];
  187. $this->_root = &$value['name'];
  188. return true;
  189. }
  190. // parent has to be an array
  191. if (!isset($parent['children']) || !is_array($parent['children'])) {
  192. $parent['children'] = array();
  193. if ($parent['type'] != 'array') {
  194. $parent['type'] = 'array';
  195. }
  196. }
  197. if (!empty($value['name'])) {
  198. // there already has been a tag with this name
  199. if (in_array($value['name'], $parent['childrenKeys'])) {
  200. // no aggregate has been created for this tag
  201. if (!in_array($value['name'], $parent['aggregKeys'])) {
  202. if (isset($parent['children'][$value['name']])) {
  203. $parent['children'][$value['name']] = array($parent['children'][$value['name']]);
  204. } else {
  205. $parent['children'][$value['name']] = array();
  206. }
  207. array_push($parent['aggregKeys'], $value['name']);
  208. }
  209. array_push($parent['children'][$value['name']], $value['value']);
  210. } else {
  211. $parent['children'][$value['name']] = &$value['value'];
  212. array_push($parent['childrenKeys'], $value['name']);
  213. }
  214. } else {
  215. array_push($parent['children'],$value['value']);
  216. }
  217. array_push($this->_valStack, $parent);
  218. $this->_depth--;
  219. }
  220. /**
  221. * Handler for character data
  222. *
  223. * @access private
  224. * @param object XML parser object
  225. * @param string CDATA
  226. * @return void
  227. */
  228. function cdataHandler($parser, $cdata)
  229. {
  230. $this->_dataStack[$this->_depth] .= $cdata;
  231. }
  232. }