/core/src/main/php/xml/parser/XMLParser.class.php

https://github.com/oanas/xp-framework · PHP · 158 lines · 75 code · 14 blank · 69 comment · 13 complexity · 597b0a42f5e0a794aa467cea9786ca97 MD5 · raw file

  1. <?php
  2. /* This class is part of the XP framework
  3. *
  4. * $Id$
  5. */
  6. uses('xml.XMLFormatException');
  7. /**
  8. * XML Parser
  9. *
  10. * Example:
  11. * <code>
  12. * uses('xml.parser.XMLParser');
  13. *
  14. * $parser= new XMLParser();
  15. * $parser->setCallback(...);
  16. * try {
  17. * $parser->parse($xml);
  18. * } catch (XMLFormatException $e) {
  19. * $e->printStackTrace();
  20. * exit(-1);
  21. * }
  22. * </code>
  23. *
  24. * @ext xml
  25. * @test xp://net.xp_framework.unittest.xml.StreamXMLParserTest
  26. * @test xp://net.xp_framework.unittest.xml.StringXMLParserTest
  27. */
  28. class XMLParser extends Object {
  29. public
  30. $encoding = '',
  31. $callback = NULL;
  32. /**
  33. * Constructor
  34. *
  35. * @param string encoding default 'ISO-8859-1'
  36. */
  37. public function __construct($encoding= 'ISO-8859-1') {
  38. $this->encoding= $encoding;
  39. }
  40. /**
  41. * Set callback
  42. *
  43. * @param xml.parser.ParserCallback callback
  44. */
  45. public function setCallback($callback) {
  46. $this->callback= $callback;
  47. }
  48. /**
  49. * Set callback
  50. *
  51. * @param xml.parser.ParserCallback callback
  52. * @return xml.parser.XMLParser this
  53. */
  54. public function withCallback($callback) {
  55. $this->callback= $callback;
  56. return $this;
  57. }
  58. /**
  59. * Set Encoding
  60. *
  61. * @param string encoding
  62. */
  63. public function setEncoding($encoding) {
  64. $this->encoding= $encoding;
  65. }
  66. /**
  67. * Set Encoding
  68. *
  69. * @param string encoding
  70. * @return xml.parser.XMLParser this
  71. */
  72. public function withEncoding($encoding) {
  73. $this->encoding= $encoding;
  74. return $this;
  75. }
  76. /**
  77. * Get Encoding
  78. *
  79. * @return string
  80. */
  81. public function getEncoding() {
  82. return $this->encoding;
  83. }
  84. /**
  85. * Parse XML data
  86. *
  87. * @param var data either a string or an xml.parser.InputSource
  88. * @param string source default NULL optional source identifier, will show up in exception
  89. * @return bool
  90. * @throws xml.XMLFormatException in case the data could not be parsed
  91. * @throws lang.NullPointerException in case a parser could not be created
  92. */
  93. public function parse($data, $source= NULL) {
  94. if ($parser= xml_parser_create('')) {
  95. xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, FALSE);
  96. if (NULL === $this->encoding) {
  97. $this->encoding= xml_parser_get_option($parser, XML_OPTION_TARGET_ENCODING);
  98. } else {
  99. xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $this->encoding);
  100. }
  101. // Register callback
  102. if ($this->callback) {
  103. xml_set_object($parser, $this->callback);
  104. $this->callback->onBegin($this);
  105. xml_set_element_handler($parser, 'onStartElement', 'onEndElement');
  106. xml_set_character_data_handler($parser, 'onCData');
  107. xml_set_default_handler($parser, 'onDefault');
  108. }
  109. // Parse streams while reading data
  110. if ($data instanceof InputSource) {
  111. $stream= $data->getStream();
  112. $source || $source= $data->getSource();
  113. do {
  114. if ($stream->available()) {
  115. $r= xml_parse($parser, $stream->read(), FALSE);
  116. } else {
  117. $r= xml_parse($parser, '', TRUE);
  118. break;
  119. }
  120. } while ($r);
  121. } else {
  122. $r= xml_parse($parser, $data, TRUE);
  123. }
  124. // Check for errors
  125. if (!$r) {
  126. $type= xml_get_error_code($parser);
  127. $line= xml_get_current_line_number($parser);
  128. $column= xml_get_current_column_number($parser);
  129. $message= xml_error_string($type);
  130. xml_parser_free($parser);
  131. libxml_clear_errors();
  132. $e= new XMLFormatException($message, $type, $source, $line, $column);
  133. $this->callback && $this->callback->onError($this, $e);
  134. throw $e;
  135. }
  136. xml_parser_free($parser);
  137. $r= TRUE;
  138. $this->callback && $r= $this->callback->onFinish($this);
  139. return $r;
  140. }
  141. throw new NullPointerException('Could not create parser');
  142. }
  143. }
  144. ?>