123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #include "cmXMLParser.h"
- #include "cm_expat.h"
- #include "cmsys/FStream.hxx"
- #include <ctype.h>
- #include <iostream>
- #include <sstream>
- #include <string.h>
- cmXMLParser::cmXMLParser()
- {
- this->Parser = nullptr;
- this->ParseError = 0;
- this->ReportCallback = nullptr;
- this->ReportCallbackData = nullptr;
- }
- cmXMLParser::~cmXMLParser()
- {
- if (this->Parser) {
- this->CleanupParser();
- }
- }
- int cmXMLParser::Parse(const char* string)
- {
- return this->InitializeParser() &&
- this->ParseChunk(string, strlen(string)) && this->CleanupParser();
- }
- int cmXMLParser::ParseFile(const char* file)
- {
- if (!file) {
- return 0;
- }
- cmsys::ifstream ifs(file);
- if (!ifs) {
- return 0;
- }
- std::ostringstream 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(nullptr);
- XML_SetElementHandler(static_cast<XML_Parser>(this->Parser),
- &cmXMLParserStartElement, &cmXMLParserEndElement);
- XML_SetCharacterDataHandler(static_cast<XML_Parser>(this->Parser),
- &cmXMLParserCharacterDataHandler);
- XML_SetUserData(static_cast<XML_Parser>(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<XML_Parser>(this->Parser), "", 0, 1)) {
- this->ReportXmlParseError();
- result = 0;
- }
- }
- // Clean up the parser.
- XML_ParserFree(static_cast<XML_Parser>(this->Parser));
- this->Parser = nullptr;
- 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<XML_Parser>(this->Parser), buffer,
- static_cast<int>(count), 0)) {
- this->ReportXmlParseError();
- return 0;
- }
- return 1;
- }
- int cmXMLParser::ParseBuffer(const char* buffer)
- {
- return this->ParseBuffer(buffer, static_cast<int>(strlen(buffer)));
- }
- int cmXMLParser::ParsingComplete()
- {
- // Default behavior is to parse to end of stream.
- return 0;
- }
- void cmXMLParser::StartElement(const std::string& name, const char** /*atts*/)
- {
- std::cout << "Start element: " << name << std::endl;
- }
- void cmXMLParser::EndElement(const std::string& 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 nullptr;
- }
- 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<cmXMLParser*>(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<cmXMLParser*>(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<cmXMLParser*>(parser)->CharacterDataHandler(data, length);
- }
- void cmXMLParser::ReportXmlParseError()
- {
- XML_Parser parser = static_cast<XML_Parser>(this->Parser);
- this->ReportError(XML_GetCurrentLineNumber(parser),
- XML_GetCurrentColumnNumber(parser),
- XML_ErrorString(XML_GetErrorCode(parser)));
- }
- void cmXMLParser::ReportError(int line, int /*unused*/, const char* msg)
- {
- if (this->ReportCallback) {
- this->ReportCallback(line, msg, this->ReportCallbackData);
- } else {
- std::cerr << "Error parsing XML in stream at line " << line << ": " << msg
- << std::endl;
- }
- }
|