/*============================================================================ CMake - Cross Platform Makefile Generator Copyright 2000-2009 Kitware, Inc., Insight Software Consortium Distributed under the OSI-approved BSD License (the "License"); see accompanying file Copyright.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ #include "cmXMLParser.h" #include #include //---------------------------------------------------------------------------- cmXMLParser::cmXMLParser() { this->Parser = 0; this->ParseError = 0; } //---------------------------------------------------------------------------- cmXMLParser::~cmXMLParser() { if ( this->Parser ) { this->CleanupParser(); } } //---------------------------------------------------------------------------- int cmXMLParser::Parse(const char* string) { return (int)this->InitializeParser() && this->ParseChunk(string, strlen(string)) && this->CleanupParser(); } int cmXMLParser::ParseFile(const char* file) { if ( !file ) { return 0; } std::ifstream ifs(file); if ( !ifs ) { return 0; } cmOStringStream str; str << ifs.rdbuf(); return this->Parse(str.str().c_str()); } //---------------------------------------------------------------------------- int cmXMLParser::InitializeParser() { if ( this->Parser ) { std::cerr << "Parser already initialized" << std::endl; this->ParseError = 1; return 0; } // Create the expat XML parser. this->Parser = XML_ParserCreate(0); XML_SetElementHandler(static_cast(this->Parser), &cmXMLParserStartElement, &cmXMLParserEndElement); XML_SetCharacterDataHandler(static_cast(this->Parser), &cmXMLParserCharacterDataHandler); XML_SetUserData(static_cast(this->Parser), this); this->ParseError = 0; return 1; } //---------------------------------------------------------------------------- int cmXMLParser::ParseChunk(const char* inputString, std::string::size_type length) { if ( !this->Parser ) { std::cerr << "Parser not initialized" << std::endl; this->ParseError = 1; return 0; } int res; res = this->ParseBuffer(inputString, length); if ( res == 0 ) { this->ParseError = 1; } return res; } //---------------------------------------------------------------------------- int cmXMLParser::CleanupParser() { if ( !this->Parser ) { std::cerr << "Parser not initialized" << std::endl; this->ParseError = 1; return 0; } int result = !this->ParseError; if(result) { // Tell the expat XML parser about the end-of-input. if(!XML_Parse(static_cast(this->Parser), "", 0, 1)) { this->ReportXmlParseError(); result = 0; } } // Clean up the parser. XML_ParserFree(static_cast(this->Parser)); this->Parser = 0; return result; } //---------------------------------------------------------------------------- int cmXMLParser::ParseBuffer(const char* buffer, std::string::size_type count) { // Pass the buffer to the expat XML parser. if(!XML_Parse(static_cast(this->Parser), buffer, static_cast(count), 0)) { this->ReportXmlParseError(); return 0; } return 1; } //---------------------------------------------------------------------------- int cmXMLParser::ParseBuffer(const char* buffer) { return this->ParseBuffer(buffer, static_cast(strlen(buffer))); } //---------------------------------------------------------------------------- int cmXMLParser::ParsingComplete() { // Default behavior is to parse to end of stream. return 0; } //---------------------------------------------------------------------------- void cmXMLParser::StartElement(const char * name, const char ** /*atts*/) { std::cout << "Start element: " << name << std::endl; } //---------------------------------------------------------------------------- void cmXMLParser::EndElement(const char * name) { std::cout << "End element: " << name << std::endl; } //---------------------------------------------------------------------------- void cmXMLParser::CharacterDataHandler(const char* /*inData*/, int /*inLength*/) { } //---------------------------------------------------------------------------- int cmXMLParser::IsSpace(char c) { return isspace(c); } //---------------------------------------------------------------------------- const char* cmXMLParser::FindAttribute(const char** atts, const char* attribute) { if(atts && attribute) { for(const char** a = atts; *a && *(a+1); a += 2) { if(strcmp(*a, attribute) == 0) { return *(a+1); } } } return 0; } //---------------------------------------------------------------------------- void cmXMLParserStartElement(void* parser, const char *name, const char **atts) { // Begin element handler that is registered with the XML_Parser. // This just casts the user data to a cmXMLParser and calls // StartElement. static_cast(parser)->StartElement(name, atts); } //---------------------------------------------------------------------------- void cmXMLParserEndElement(void* parser, const char *name) { // End element handler that is registered with the XML_Parser. This // just casts the user data to a cmXMLParser and calls EndElement. static_cast(parser)->EndElement(name); } //---------------------------------------------------------------------------- void cmXMLParserCharacterDataHandler(void* parser, const char* data, int length) { // Character data handler that is registered with the XML_Parser. // This just casts the user data to a cmXMLParser and calls // CharacterDataHandler. static_cast(parser)->CharacterDataHandler(data, length); } //---------------------------------------------------------------------------- void cmXMLParser::ReportXmlParseError() { XML_Parser parser = static_cast(this->Parser); this->ReportError(XML_GetCurrentLineNumber(parser), XML_GetCurrentColumnNumber(parser), XML_ErrorString(XML_GetErrorCode(parser))); } //---------------------------------------------------------------------------- void cmXMLParser::ReportError(int line, int, const char* msg) { std::cerr << "Error parsing XML in stream at line " << line << ": " << msg << std::endl; }