1
0

cmXMLParser.cxx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmXMLParser.h"
  11. #include <cmsys/FStream.hxx>
  12. #include <cm_expat.h>
  13. #include <ctype.h>
  14. //----------------------------------------------------------------------------
  15. cmXMLParser::cmXMLParser()
  16. {
  17. this->Parser = 0;
  18. this->ParseError = 0;
  19. }
  20. //----------------------------------------------------------------------------
  21. cmXMLParser::~cmXMLParser()
  22. {
  23. if ( this->Parser )
  24. {
  25. this->CleanupParser();
  26. }
  27. }
  28. //----------------------------------------------------------------------------
  29. int cmXMLParser::Parse(const char* string)
  30. {
  31. return (int)this->InitializeParser() &&
  32. this->ParseChunk(string, strlen(string)) &&
  33. this->CleanupParser();
  34. }
  35. int cmXMLParser::ParseFile(const char* file)
  36. {
  37. if ( !file )
  38. {
  39. return 0;
  40. }
  41. cmsys::ifstream ifs(file);
  42. if ( !ifs )
  43. {
  44. return 0;
  45. }
  46. cmOStringStream str;
  47. str << ifs.rdbuf();
  48. return this->Parse(str.str().c_str());
  49. }
  50. //----------------------------------------------------------------------------
  51. int cmXMLParser::InitializeParser()
  52. {
  53. if ( this->Parser )
  54. {
  55. std::cerr << "Parser already initialized" << std::endl;
  56. this->ParseError = 1;
  57. return 0;
  58. }
  59. // Create the expat XML parser.
  60. this->Parser = XML_ParserCreate(0);
  61. XML_SetElementHandler(static_cast<XML_Parser>(this->Parser),
  62. &cmXMLParserStartElement,
  63. &cmXMLParserEndElement);
  64. XML_SetCharacterDataHandler(static_cast<XML_Parser>(this->Parser),
  65. &cmXMLParserCharacterDataHandler);
  66. XML_SetUserData(static_cast<XML_Parser>(this->Parser), this);
  67. this->ParseError = 0;
  68. return 1;
  69. }
  70. //----------------------------------------------------------------------------
  71. int cmXMLParser::ParseChunk(const char* inputString,
  72. std::string::size_type length)
  73. {
  74. if ( !this->Parser )
  75. {
  76. std::cerr << "Parser not initialized" << std::endl;
  77. this->ParseError = 1;
  78. return 0;
  79. }
  80. int res;
  81. res = this->ParseBuffer(inputString, length);
  82. if ( res == 0 )
  83. {
  84. this->ParseError = 1;
  85. }
  86. return res;
  87. }
  88. //----------------------------------------------------------------------------
  89. int cmXMLParser::CleanupParser()
  90. {
  91. if ( !this->Parser )
  92. {
  93. std::cerr << "Parser not initialized" << std::endl;
  94. this->ParseError = 1;
  95. return 0;
  96. }
  97. int result = !this->ParseError;
  98. if(result)
  99. {
  100. // Tell the expat XML parser about the end-of-input.
  101. if(!XML_Parse(static_cast<XML_Parser>(this->Parser), "", 0, 1))
  102. {
  103. this->ReportXmlParseError();
  104. result = 0;
  105. }
  106. }
  107. // Clean up the parser.
  108. XML_ParserFree(static_cast<XML_Parser>(this->Parser));
  109. this->Parser = 0;
  110. return result;
  111. }
  112. //----------------------------------------------------------------------------
  113. int cmXMLParser::ParseBuffer(const char* buffer, std::string::size_type count)
  114. {
  115. // Pass the buffer to the expat XML parser.
  116. if(!XML_Parse(static_cast<XML_Parser>(this->Parser), buffer,
  117. static_cast<int>(count), 0))
  118. {
  119. this->ReportXmlParseError();
  120. return 0;
  121. }
  122. return 1;
  123. }
  124. //----------------------------------------------------------------------------
  125. int cmXMLParser::ParseBuffer(const char* buffer)
  126. {
  127. return this->ParseBuffer(buffer, static_cast<int>(strlen(buffer)));
  128. }
  129. //----------------------------------------------------------------------------
  130. int cmXMLParser::ParsingComplete()
  131. {
  132. // Default behavior is to parse to end of stream.
  133. return 0;
  134. }
  135. //----------------------------------------------------------------------------
  136. void cmXMLParser::StartElement(const std::string& name,
  137. const char ** /*atts*/)
  138. {
  139. std::cout << "Start element: " << name << std::endl;
  140. }
  141. //----------------------------------------------------------------------------
  142. void cmXMLParser::EndElement(const std::string& name)
  143. {
  144. std::cout << "End element: " << name << std::endl;
  145. }
  146. //----------------------------------------------------------------------------
  147. void cmXMLParser::CharacterDataHandler(const char* /*inData*/,
  148. int /*inLength*/)
  149. {
  150. }
  151. //----------------------------------------------------------------------------
  152. int cmXMLParser::IsSpace(char c)
  153. {
  154. return isspace(c);
  155. }
  156. //----------------------------------------------------------------------------
  157. const char* cmXMLParser::FindAttribute(const char** atts,
  158. const char* attribute)
  159. {
  160. if(atts && attribute)
  161. {
  162. for(const char** a = atts; *a && *(a+1); a += 2)
  163. {
  164. if(strcmp(*a, attribute) == 0)
  165. {
  166. return *(a+1);
  167. }
  168. }
  169. }
  170. return 0;
  171. }
  172. //----------------------------------------------------------------------------
  173. void cmXMLParserStartElement(void* parser, const char *name,
  174. const char **atts)
  175. {
  176. // Begin element handler that is registered with the XML_Parser.
  177. // This just casts the user data to a cmXMLParser and calls
  178. // StartElement.
  179. static_cast<cmXMLParser*>(parser)->StartElement(name, atts);
  180. }
  181. //----------------------------------------------------------------------------
  182. void cmXMLParserEndElement(void* parser, const char *name)
  183. {
  184. // End element handler that is registered with the XML_Parser. This
  185. // just casts the user data to a cmXMLParser and calls EndElement.
  186. static_cast<cmXMLParser*>(parser)->EndElement(name);
  187. }
  188. //----------------------------------------------------------------------------
  189. void cmXMLParserCharacterDataHandler(void* parser, const char* data,
  190. int length)
  191. {
  192. // Character data handler that is registered with the XML_Parser.
  193. // This just casts the user data to a cmXMLParser and calls
  194. // CharacterDataHandler.
  195. static_cast<cmXMLParser*>(parser)->CharacterDataHandler(data, length);
  196. }
  197. //----------------------------------------------------------------------------
  198. void cmXMLParser::ReportXmlParseError()
  199. {
  200. XML_Parser parser = static_cast<XML_Parser>(this->Parser);
  201. this->ReportError(XML_GetCurrentLineNumber(parser),
  202. XML_GetCurrentColumnNumber(parser),
  203. XML_ErrorString(XML_GetErrorCode(parser)));
  204. }
  205. //----------------------------------------------------------------------------
  206. void cmXMLParser::ReportError(int line, int, const char* msg)
  207. {
  208. std::cerr << "Error parsing XML in stream at line "
  209. << line << ": " << msg << std::endl;
  210. }