PageRenderTime 75ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/src/ParseXML/ParseXML.php

https://github.com/dreamsxin/parse-xml
PHP | 179 lines | 127 code | 23 blank | 29 comment | 14 complexity | 26a98300201da25f2e2b397ce9894671 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Parse XML package.
  4. *
  5. * (c) Matthieu Bilbille
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace ParseXML;
  11. define('PX_STATUS_NULL', 0);
  12. define('PX_STATUS_OPEN', 1);
  13. define('PX_STATUS_READING', 2);
  14. define('PX_STATUS_CLOSE', 3);
  15. /**
  16. * A basic XML parser using the default PHP XML Parser.
  17. */
  18. class ParseXML
  19. {
  20. private $parser;
  21. private $name;
  22. private $class;
  23. private $callback;
  24. private $pointer;
  25. private $data = null;
  26. private $element = null;
  27. public function __construct($name, $class, $callback)
  28. {
  29. $this->name = $name;
  30. $this->class = $class;
  31. $this->callback = $callback;
  32. $this->pointer = new ParseXMLPointer();
  33. $this->parser = xml_parser_create();
  34. xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
  35. xml_set_object($this->parser, $this);
  36. xml_set_element_handler($this->parser, "startElement", "endElement");
  37. xml_set_default_handler($this->parser, "defaultData");
  38. }
  39. public function __destruct()
  40. {
  41. xml_parser_free($this->parser);
  42. $this->parser = null;
  43. $this->pointer = null;
  44. }
  45. /**
  46. * Just a wrapper to call xml_parse.
  47. */
  48. public function parse($data)
  49. {
  50. if (!xml_parse($this->parser, $data)) {
  51. throw new \Exception(sprintf("XML error : %s while parsing %d", xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser)), 1);
  52. }
  53. }
  54. /**
  55. * Parse a file.
  56. */
  57. public function parseFile($file)
  58. {
  59. if (!($fp = fopen($file, "r"))) {
  60. throw new \Exception("Cannot open " . $file, 1);
  61. }
  62. while ($data = fread($fp, 65536)) {
  63. $this->parse($data);
  64. }
  65. fclose($fp);
  66. }
  67. /**
  68. * Handler tag opening.
  69. */
  70. private function startElement($parser, $tag, $attributes)
  71. {
  72. if ($tag === $this->name) {
  73. $this->element = new $this->class($attributes);
  74. }
  75. if (is_null($this->element)) {
  76. return true;
  77. }
  78. $this->pointer->tag = $tag;
  79. $this->pointer->attributes = $attributes;
  80. $this->pointer->status = PX_STATUS_OPEN;
  81. $this->data = null;
  82. $this->maker();
  83. }
  84. /**
  85. * Handle data processing.
  86. */
  87. private function defaultData($parser, $data)
  88. {
  89. if ($this->pointer->status === PX_STATUS_OPEN) {
  90. $this->data = $data;
  91. $this->pointer->status = PX_STATUS_READING;
  92. } elseif ($this->pointer->status === PX_STATUS_READING) {
  93. $this->data .= $data;
  94. } else {
  95. return false;
  96. }
  97. }
  98. /**
  99. * Handles tag closure.
  100. */
  101. private function endElement($parser, $tag)
  102. {
  103. if ($this->pointer->status === PX_STATUS_NULL) {
  104. return false;
  105. }
  106. if ($this->pointer->status !== PX_STATUS_CLOSE) {
  107. $this->setter($this->data, $this->pointer->attributes);
  108. }
  109. if ($tag === $this->name) {
  110. $callback = $this->callback;
  111. if (is_callable($callback)) {
  112. $callback($this->element);
  113. }
  114. unset($this->element);
  115. $this->element = null;
  116. }
  117. $this->pointer->status = PX_STATUS_CLOSE;
  118. }
  119. /**
  120. * Call object initter && setter.
  121. */
  122. private function maker()
  123. {
  124. $maker = 'make' . $this->pointer->tag;
  125. if (method_exists($this->class, $maker)) {
  126. $this->element->$maker();
  127. }
  128. }
  129. private function setter($data = null, $attributes = array())
  130. {
  131. $setter = 'set' . $this->pointer->tag;
  132. if (method_exists($this->class, $setter)) {
  133. $this->element->$setter($data, $attributes);
  134. }
  135. }
  136. }
  137. class ParseXMLPointer
  138. {
  139. private $tag;
  140. private $attributes;
  141. private $status;
  142. public function __construct()
  143. {
  144. $this->tag = '';
  145. $this->attributes = array();
  146. $this->status = PX_STATUS_NULL;
  147. }
  148. public function __get($name)
  149. {
  150. return $this->$name;
  151. }
  152. public function __set($name, $value)
  153. {
  154. $this->$name = $value;
  155. }
  156. }