#ifndef _XML_PARSER_H_ #define _XML_PARSER_H_ #include "expat.h" //#include "XML.h" #include template class LazyCondition { public: typedef bool (*cond_fct)(OperandType op1, OperandType op2); LazyCondition(OperandType op1, OperandType op2, cond_fct fct) : _op1(op1), _op2(op2), _fct(fct) {}; bool check() { return _fct(_op1,_op2); } private: OperandType _op1; OperandType _op2; cond_fct _fct; }; inline bool lazyStrEqual(const char* str1, const char* str2) { return strcmp(str1,str2) == 0; } class LazyStrEqual : public LazyCondition { public: LazyStrEqual(const char* str1, const char* str2) : LazyCondition(str1, str2, lazyStrEqual) {}; }; class LazyTrue : public LazyCondition { static bool True(bool a, bool b){return true;}; public: LazyTrue() : LazyCondition(true,true,LazyTrue::True) {}; }; class IXMLParser { public: const XML_Char* ElementName; public: IXMLParser(const XML_Char *element_name, XML_Parser* parser, IXMLParser* caller=NULL) : _caller(caller), ElementName(element_name) { if(parser) { this->setParser(parser); } }; ~IXMLParser() {}; /** * Interface */ static void onStartCallback(void *userData, const XML_Char* name, const XML_Char** atts) { ((IXMLParser*)userData)->onStartElement(name,atts); } static void onEndCallback(void *userData, const XML_Char* name) { ((IXMLParser*)userData)->onEndElement(name); // test if we are done here if( ((IXMLParser*)userData)->_caller && (strcmp(name, ((IXMLParser*)userData)->ElementName) == 0) ) { ((IXMLParser*)userData)->_caller->grabParser(); } } static void onTextCallback(void *userData, const XML_Char *str, int len) { ((IXMLParser*)userData)->onTextElement(str,len); } void grabParser() { XML_SetUserData(*_parser,this); XML_SetElementHandler(*_parser, IXMLParser::onStartCallback, IXMLParser::onEndCallback); XML_SetCharacterDataHandler(*_parser, IXMLParser::onTextCallback); } /** * Override these methods in your parser */ virtual void onStartElement(const XML_Char* name, const XML_Char** atts) {}; virtual void onEndElement(const XML_Char* name) {}; virtual void onTextElement(const XML_Char *str, int len) { }; class Attributes { public: Attributes(const XML_Char** atts) : _atts(atts) {}; XML_Char const* get(const XML_Char* attr_name) const { const XML_Char** atts = _atts; while(*atts) { if(strcmp(*atts++,attr_name) == 0) { return *atts; } atts++; } return ""; } bool getLong(const XML_Char* attr_name, long& attr) const { XML_Char const* result = this->get(attr_name); if( strcmp(result,"") != 0) { attr = (int)atol(result); return true; } return false; } bool getDouble(const XML_Char* attr_name, double &attr) const { XML_Char const* result = this->get(attr_name); if( strcmp(result,"") != 0) { attr = atof(result); return true; } return false; } private: const XML_Char** _atts; }; template class ParserState { public: ParserState(const StateType start_state) : _my_state(start_state) {}; StateType const& state() { return _my_state; } template bool stateTransition(const StateType current_state, LazyCondition condition, const StateType next_state) { if(_my_state == current_state && condition.check() ) { _my_state = next_state; return true; } return false; } private: StateType _my_state; }; XML_Parser& getParser() { return *_parser; } protected: void setParser(XML_Parser* parser) { _parser = parser; // grabParser(); ??? } XML_Char const* getAttribute(const XML_Char* attr_name, const XML_Char** atts) { while(*atts) { if(strcmp(*atts++,attr_name) == 0) { return *atts; } atts++; } return ""; } bool getAttributeAsInt(const XML_Char* attr_name, const XML_Char** attr, int &value) { XML_Char const* result = getAttribute(attr_name,attr); if( strcmp(result,"") != 0) { value = (int)atol(result); return true; } return false; } bool getAttributeAsFloat(const XML_Char* attr_name, const XML_Char** attr, float &value) { XML_Char const* result = getAttribute(attr_name,attr); if( strcmp(result,"") != 0) { value = (float)atof(result); return true; } return false; } int getCurrentLineNumber() { return XML_GetCurrentLineNumber(*this->_parser); } protected: std::string sCharData; XML_Parser* _parser; IXMLParser* _caller; }; #endif // _XML_PARSER_H_