/gespac/config/PEAR/PEAR/XMLParser.php

http://gespac.googlecode.com/ · PHP · 253 lines · 127 code · 26 blank · 100 comment · 24 complexity · de6c3f7f8676896a36eef666c751987e 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 282970 2009-06-28 23:10:07Z dufuz $
  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.9.1
  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->_dataStack = $this->_valStack = array();
  79. $this->_depth = 0;
  80. if (
  81. strpos($data, 'encoding="UTF-8"')
  82. || strpos($data, 'encoding="utf-8"')
  83. || strpos($data, "encoding='UTF-8'")
  84. || strpos($data, "encoding='utf-8'")
  85. ) {
  86. $this->encoding = 'UTF-8';
  87. }
  88. if (version_compare(phpversion(), '5.0.0', 'lt') && $this->encoding == 'UTF-8') {
  89. $data = utf8_decode($data);
  90. $this->encoding = 'ISO-8859-1';
  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. $this->_depth++;
  119. $this->_dataStack[$this->_depth] = null;
  120. $val = array(
  121. 'name' => $element,
  122. 'value' => null,
  123. 'type' => 'string',
  124. 'childrenKeys' => array(),
  125. 'aggregKeys' => array()
  126. );
  127. if (count($attribs) > 0) {
  128. $val['children'] = array();
  129. $val['type'] = 'array';
  130. $val['children']['attribs'] = $attribs;
  131. }
  132. array_push($this->_valStack, $val);
  133. }
  134. /**
  135. * post-process data
  136. *
  137. * @param string $data
  138. * @param string $element element name
  139. */
  140. function postProcess($data, $element)
  141. {
  142. return trim($data);
  143. }
  144. /**
  145. * End element handler for XML parser
  146. *
  147. * @access private
  148. * @param object XML parser object
  149. * @param string
  150. * @return void
  151. */
  152. function endHandler($parser, $element)
  153. {
  154. $value = array_pop($this->_valStack);
  155. $data = $this->postProcess($this->_dataStack[$this->_depth], $element);
  156. // adjust type of the value
  157. switch (strtolower($value['type'])) {
  158. // unserialize an array
  159. case 'array':
  160. if ($data !== '') {
  161. $value['children']['_content'] = $data;
  162. }
  163. $value['value'] = isset($value['children']) ? $value['children'] : array();
  164. break;
  165. /*
  166. * unserialize a null value
  167. */
  168. case 'null':
  169. $data = null;
  170. break;
  171. /*
  172. * unserialize any scalar value
  173. */
  174. default:
  175. settype($data, $value['type']);
  176. $value['value'] = $data;
  177. break;
  178. }
  179. $parent = array_pop($this->_valStack);
  180. if ($parent === null) {
  181. $this->_unserializedData = &$value['value'];
  182. $this->_root = &$value['name'];
  183. return true;
  184. }
  185. // parent has to be an array
  186. if (!isset($parent['children']) || !is_array($parent['children'])) {
  187. $parent['children'] = array();
  188. if ($parent['type'] != 'array') {
  189. $parent['type'] = 'array';
  190. }
  191. }
  192. if (!empty($value['name'])) {
  193. // there already has been a tag with this name
  194. if (in_array($value['name'], $parent['childrenKeys'])) {
  195. // no aggregate has been created for this tag
  196. if (!in_array($value['name'], $parent['aggregKeys'])) {
  197. if (isset($parent['children'][$value['name']])) {
  198. $parent['children'][$value['name']] = array($parent['children'][$value['name']]);
  199. } else {
  200. $parent['children'][$value['name']] = array();
  201. }
  202. array_push($parent['aggregKeys'], $value['name']);
  203. }
  204. array_push($parent['children'][$value['name']], $value['value']);
  205. } else {
  206. $parent['children'][$value['name']] = &$value['value'];
  207. array_push($parent['childrenKeys'], $value['name']);
  208. }
  209. } else {
  210. array_push($parent['children'],$value['value']);
  211. }
  212. array_push($this->_valStack, $parent);
  213. $this->_depth--;
  214. }
  215. /**
  216. * Handler for character data
  217. *
  218. * @access private
  219. * @param object XML parser object
  220. * @param string CDATA
  221. * @return void
  222. */
  223. function cdataHandler($parser, $cdata)
  224. {
  225. $this->_dataStack[$this->_depth] .= $cdata;
  226. }
  227. }