diff options
Diffstat (limited to 'addon/xmlparse/basehandler.h')
-rw-r--r-- | addon/xmlparse/basehandler.h | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/addon/xmlparse/basehandler.h b/addon/xmlparse/basehandler.h new file mode 100644 index 0000000..2d037e0 --- /dev/null +++ b/addon/xmlparse/basehandler.h @@ -0,0 +1,252 @@ +#ifndef _BASEHANDLER_H +#define _BASEHANDLER_H + +#include <qxml.h> +#include <qdict.h> +#include <qstring.h> + +class IBaseHandler +{ + public: + virtual void setDelegate(QXmlDefaultHandler *delegate) = 0; + virtual QXmlDefaultHandler *delegate() const = 0; +}; + +class IFallBackHandler +{ + public: + virtual bool handleStartElement(const QString & name, + const QXmlAttributes & attrib) = 0; + virtual bool handleEndElement(const QString &name) = 0; +}; + +template<class T> class ElementMapper +{ + class StartElementHandler + { + typedef void (T::*Handler)(const QXmlAttributes &attrib); + public: + StartElementHandler() : m_parent(0) {} + StartElementHandler(T *parent, Handler h) + : m_parent(parent), m_handler(h) {} + void operator()(const QXmlAttributes &attrib) + { if (m_parent) (m_parent->*m_handler)(attrib); } + private: + T *m_parent; + Handler m_handler; + }; + + class EndElementHandler + { + typedef void (T::*Handler)(); + public: + EndElementHandler() : m_parent(0) {} + EndElementHandler(T *parent, Handler h) + : m_parent(parent), m_handler(h) {} + void operator()() + { if (m_parent) (m_parent->*m_handler)(); } + private: + T *m_parent; + Handler m_handler; + }; + + typedef StartElementHandler<T> StartElementHandlerT; + typedef EndElementHandler<T> EndElementHandlerT; + + public: + ElementMapper() : m_startHandlers(67), m_endHandlers(67) + { + m_startHandlers.setAutoDelete(TRUE); + m_endHandlers.setAutoDelete(TRUE); + } + virtual ~ElementMapper() + { + } + + void addStartHandler(const char *key) + { + m_startHandlers.insert(key,new StartElementHandlerT); + } + + void addStartHandler(const char *key, T *obj, void (T::*handler)(const QXmlAttributes &)) + { + m_startHandlers.insert(key,new StartElementHandlerT(obj,handler)); + } + + void addEndHandler(const char *key) + { + m_endHandlers.insert(key,new EndElementHandlerT); + } + + void addEndHandler(const char *key, T *obj, void (T::*handler)()) + { + m_endHandlers.insert(key,new EndElementHandlerT(obj,handler)); + } + + + protected: + QDict<StartElementHandlerT> m_startHandlers; + QDict<EndElementHandlerT> m_endHandlers; +}; + +template<class T> class BaseHandler : public IBaseHandler, + public QXmlDefaultHandler, + public ElementMapper<T> +{ + public: + BaseHandler() : m_delegateHandler(0), m_fallBackHandler(0) + { + } + + virtual ~BaseHandler() + { + delete m_fallBackHandler; + } + + virtual bool startDocument() + { + return TRUE; + } + + virtual bool startElement( const QString & namespaceURI, + const QString & localName, + const QString & name, + const QXmlAttributes & attrib + ) + { + if (m_delegateHandler) + { + return m_delegateHandler->startElement(namespaceURI,localName,name,attrib); + } + if (!m_skipUntil.isEmpty()) // skip mode + { + if (m_skipUntil==name) m_skipCount++; + printf("skipping start tag %s count=%d\n",name.data(),m_skipCount); + return TRUE; + } + + StartElementHandlerT *handler = m_startHandlers[name]; + if (handler) + { + (*handler)(attrib); + //printf("found start tag %s\n",name.data()); + } + else if (m_fallBackHandler && + !m_fallBackHandler->handleStartElement(name,attrib) + ) + { + printf("found unexpected tag `%s', skipping until matching end tag\n",name.data()); + m_skipUntil = name; + m_skipCount=1; + } + return TRUE; + } + + virtual bool endElement( const QString& namespaceURI, const QString& localName, const QString& name ) + { + if (m_delegateHandler) + { + return m_delegateHandler->endElement(namespaceURI,localName,name); + } + + if (name==m_skipUntil) + { + m_skipCount--; + printf("skipping end tag %s count=%d\n",name.data(),m_skipCount); + if (m_skipCount==0) + { + m_skipUntil=""; + } + //printf("found end tag %s\n",name.data()); + } + else if (m_skipUntil.isEmpty()) + { + EndElementHandlerT *handler = m_endHandlers[name]; + if (handler) + { + (*handler)(); + //printf("found end tag %s\n",name.data()); + } + else if (m_fallBackHandler) + { + m_fallBackHandler->handleEndElement(name); + } + } + m_curString=""; + return TRUE; + } + + virtual bool characters ( const QString & ch ) + { + if (m_delegateHandler) + { + return m_delegateHandler->characters(ch); + } + + m_curString+=ch; + return TRUE; + } + + void setDelegate(QXmlDefaultHandler *delegate) + { + m_delegateHandler = delegate; + } + + QXmlDefaultHandler *delegate() const + { + return m_delegateHandler; + } + + void setFallBackHandler(IFallBackHandler *h) + { + m_fallBackHandler = h; + } + + IFallBackHandler *fallBackHandler() const + { + return m_fallBackHandler; + } + + protected: + QString m_curString; + QString m_skipUntil; + int m_skipCount; + QXmlDefaultHandler *m_delegateHandler; + IFallBackHandler *m_fallBackHandler; +}; + +template<class T> class BaseFallBackHandler : public ElementMapper<T>, + public IFallBackHandler +{ + public: + BaseFallBackHandler() + { + } + virtual ~BaseFallBackHandler() + { + } + bool handleStartElement(const QString & name, + const QXmlAttributes & attrib) + { + StartElementHandlerT *handler = m_startHandlers[name]; + if (handler) + { + (*handler)(attrib); + return TRUE; + } + return FALSE; + } + bool handleEndElement(const QString &name) + { + EndElementHandlerT *handler = m_endHandlers[name]; + if (handler) + { + (*handler)(); + return TRUE; + } + return FALSE; + } +}; + + +#endif |