ENH: Add XML parser

This commit is contained in:
Andy Cedilnik 2005-01-18 13:41:23 -05:00
parent b37b661087
commit dcadffbe00
3 changed files with 423 additions and 96 deletions

View File

@ -1,49 +1,51 @@
CMAKE_MINIMUM_REQUIRED(VERSION 1.5)
SET(SRCS
cmake.cxx
cmakewizard.cxx
cmMakeDepend.cxx
cmMakefile.cxx
cmSourceFile.cxx
cmSystemTools.cxx
cmCacheManager.cxx
cmCacheManager.h
cmCommands.cxx
cmCommands.h
cmCustomCommand.cxx
cmCustomCommand.h
cmDocumentation.cxx
cmDynamicLoader.cxx
cmCommands.cxx
cmTarget.cxx
cmCustomCommand.cxx
cmCacheManager.cxx
cmSourceGroup.cxx
cmListFileCache.cxx
cmListFileLexer.c
cmDynamicLoader.h
cmGeneratedFileStream.cxx
cmGlob.cxx
cmGlobalGenerator.cxx
cmGlobalUnixMakefileGenerator.cxx
cmLocalGenerator.cxx
cmLocalUnixMakefileGenerator.cxx
cmLocalUnixMakefileGenerator2.cxx
cmVariableWatch.cxx
cmVersion.cxx
cmake.h
cmakewizard.h
cmMakeDepend.h
cmMakefile.h
cmSourceFile.h
cmSystemTools.h
cmDynamicLoader.h
cmCommands.h
cmTarget.h
cmCustomCommand.h
cmCacheManager.h
cmSourceGroup.h
cmListFileCache.h
cmGlobalGenerator.h
cmGlobalUnixMakefileGenerator.cxx
cmGlobalUnixMakefileGenerator.h
cmListFileCache.cxx
cmListFileCache.h
cmListFileLexer.c
cmLocalGenerator.cxx
cmLocalGenerator.h
cmLocalUnixMakefileGenerator.cxx
cmLocalUnixMakefileGenerator.h
cmLocalUnixMakefileGenerator2.cxx
cmMakeDepend.cxx
cmMakeDepend.h
cmMakefile.cxx
cmMakefile.h
cmSourceFile.cxx
cmSourceFile.h
cmSourceGroup.cxx
cmSourceGroup.h
cmSystemTools.cxx
cmSystemTools.h
cmTarget.cxx
cmTarget.h
cmVariableWatch.cxx
cmVariableWatch.h
cmVersion.cxx
cmVersion.h
cmXMLParser.cxx
cmXMLParser.h
cmake.cxx
cmake.h
cmakewizard.cxx
cmakewizard.h
)

217
Source/cmXMLParser.cxx Normal file
View File

@ -0,0 +1,217 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "cmXMLParser.h"
#include <cmexpat/expat.h>
//----------------------------------------------------------------------------
cmXMLParser::cmXMLParser()
{
this->Parser = 0;
this->ParseError = 0;
}
//----------------------------------------------------------------------------
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;
}
std::ifstream ifs(file);
if ( !ifs )
{
return 0;
}
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(0);
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, unsigned int 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 = 0;
return result;
}
//----------------------------------------------------------------------------
int cmXMLParser::ParseBuffer(const char* buffer, unsigned int count)
{
// Pass the buffer to the expat XML parser.
if(!XML_Parse(static_cast<XML_Parser>(this->Parser), buffer, 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 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);
}
//----------------------------------------------------------------------------
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()
{
std::cerr << "Error parsing XML in stream at line "
<< XML_GetCurrentLineNumber(static_cast<XML_Parser>(this->Parser))
<< ": "
<< XML_ErrorString(XML_GetErrorCode(
static_cast<XML_Parser>(this->Parser))) << std::endl;
}

108
Source/cmXMLParser.h Normal file
View File

@ -0,0 +1,108 @@
/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef cmXMLParser_h
#define cmXMLParser_h
#include "cmStandardIncludes.h"
extern "C"
{
void cmXMLParserStartElement(void*, const char*, const char**);
void cmXMLParserEndElement(void*, const char*);
void cmXMLParserCharacterDataHandler(void*, const char*, int);
}
/** \class cmXMLParser
* \brief Helper class for performing XML parsing
*
* Superclass for all XML parsers.
*/
class cmXMLParser
{
public:
cmXMLParser();
virtual ~cmXMLParser();
//! Parse given XML string
virtual int Parse(const char* string);
//! Parse given XML file
virtual int ParseFile(const char* file);
/**
* When parsing fragments of XML or streaming XML, use the following three
* methods. InitializeParser method initialize parser but does not perform
* any actual parsing. ParseChunk parses framgent of XML. This has to match
* to what was already parsed. CleanupParser finishes parsing. If there were
* errors, CleanupParser will report them.
*/
virtual int InitializeParser();
virtual int ParseChunk(const char* inputString, unsigned int length);
virtual int CleanupParser();
protected:
//! This variable is true if there was a parse error while parsing in chunks.
int ParseError;
//1 Expat parser structure. Exists only during call to Parse().
void* Parser;
/**
* Called before each block of input is read from the stream to check if
* parsing is complete. Can be replaced by subclasses to change the
* terminating condition for parsing. Parsing always stops when the end of
* file is reached in the stream.
*/
virtual int ParsingComplete();
/**
* Called when a new element is opened in the XML source. Should be replaced
* by subclasses to handle each element.
* name = Name of new element.
* atts = Null-terminated array of attribute name/value pairs. Even
* indices are attribute names, and odd indices are values.
*/
virtual void StartElement(const char* name, const char** atts);
//! Called at the end of an element in the XML source opened when StartElement
// was called.
virtual void EndElement(const char* name);
//! Called when there is character data to handle.
virtual void CharacterDataHandler(const char* data, int length);
//! Called by Parse to report an XML syntax error.
virtual void ReportXmlParseError();
//! Utility for convenience of subclasses. Wraps isspace C library
// routine.
static int IsSpace(char c);
//! Send the given buffer to the XML parser.
virtual int ParseBuffer(const char* buffer, unsigned int count);
//! Send the given c-style string to the XML parser.
int ParseBuffer(const char* buffer);
//! Callbacks for the expat
friend void cmXMLParserStartElement(void*, const char*, const char**);
friend void cmXMLParserEndElement(void*, const char*);
friend void cmXMLParserCharacterDataHandler(void*, const char*, int);
};
#endif