1. Christian Fischer
  2. wiesel

Commits

Christian Fischer  committed a96cecc

new XML parser API which supports backend modules
moved libXML2 parser backend into common library

  • Participants
  • Parent commits 23a7d0f
  • Branches default

Comments (0)

Files changed (13)

File libraries/android-native/wiesel-common/Android.mk

View file
 LOCAL_MODULE_FILENAME      := libwieselcommon
 LOCAL_CFLAGS               := -Werror
 LOCAL_LDLIBS               := 
-LOCAL_STATIC_LIBRARIES     := libpng-static wiesel-base wiesel-core
+LOCAL_STATIC_LIBRARIES     := libpng-static libxml2-static wiesel-base wiesel-core
 LOCAL_SRC_FILES            := $(MY_FILES)
 LOCAL_C_INCLUDES           := $(MY_LOCAL_FOLDERS)
 LOCAL_EXPORT_C_INCLUDES    := $(MY_LOCAL_FOLDERS)
 
 # External third-party modules
 $(call import-module,third-party/libpng)
+$(call import-module,third-party/libxml)

File libraries/android-native/wiesel-common/src/wiesel/wiesel-common-config.h

View file
 // enables support for libpng
 #define WIESEL_SUPPORTS_LIBPNG 1
 
+// enables support for libxml2
+#define WIESEL_SUPPORTS_LIBXML2 1
+
+// enables support for tinyxml2
+#define WIESEL_SUPPORTS_LIBTINYXML2 0
+
 
 #endif // __WIESEL_COMMON_CONFIG_H__

File libraries/android-native/wiesel-core/Android.mk

View file
 LOCAL_MODULE_FILENAME      := libwieselcore
 LOCAL_CFLAGS               := -Werror
 LOCAL_LDLIBS               := 
-LOCAL_STATIC_LIBRARIES     := wiesel-base libxml2-static
+LOCAL_STATIC_LIBRARIES     := wiesel-base
 LOCAL_SRC_FILES            := $(MY_FILES)
 LOCAL_C_INCLUDES           := $(MY_LOCAL_FOLDERS)
 LOCAL_EXPORT_C_INCLUDES    := $(MY_LOCAL_FOLDERS)
 
 # Build the static library
 include $(BUILD_STATIC_LIBRARY)
-
-# External third-party modules
-$(call import-module,third-party/libxml)

File libraries/desktop/wiesel-common/module.cmake

View file
 wiesel_module_add_dependency(wiesel-common wiesel-core)
 
 
+# add libxml2 dependency
+include(FindLibXml2)
+
+if (LIBXML2_FOUND)
+	wiesel_target_add_includes(wiesel-common ${LIBXML2_INCLUDE_DIR})
+	wiesel_target_add_libraries(wiesel-common ${LIBXML2_LIBRARIES})
+	wiesel_target_add_compileflags(wiesel-common ${LIBXML2_DEFINITIONS})
+
+	set(WIESEL_SUPPORTS_LIBXML2		TRUE)
+else(LIBXML2_FOUND)
+	set(WIESEL_SUPPORTS_LIBXML2		FALSE)
+endif(LIBXML2_FOUND)
+
+
 # check if libpng is available
 include(FindPNG)
 

File libraries/desktop/wiesel-core/module.cmake

View file
 
 # add required modules
 wiesel_module_add_dependency(wiesel-core wiesel-base)
-
-
-# add libxml2 dependency
-include(FindLibXml2)
-
-if(DEFINED LIBXML2_FOUND)
-	wiesel_target_add_includes(wiesel-core ${LIBXML2_INCLUDE_DIR})
-	wiesel_target_add_libraries(wiesel-core ${LIBXML2_LIBRARIES})
-	wiesel_target_add_compileflags(wiesel-core ${LIBXML2_DEFINITIONS})
-else()
-	message(FATAL_ERROR "required library libxml2 not found!")
-endif()

File samples/HelloWiesel/android/jni/module_registry.cpp

View file
 
 #include "wiesel/resources/graphics/image_loader_libpng.loadable_module"
+#include "wiesel/util/libxml_sax_parser.loadable_module"
 #include "wiesel/generic_platform.loadable_module"
 
 #include "wiesel/android/util/log_writer_android.loadable_module"

File src/common/wiesel/util/libxml_sax_parser.cpp

View file
+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#include "libxml_sax_parser.h"
+
+#if WIESEL_SUPPORTS_LIBXML2
+
+#include <wiesel/io/databuffer.h>
+#include <wiesel/io/datasource.h>
+#include <wiesel/io/file.h>
+#include <wiesel/util/log.h>
+
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlversion.h>
+
+#include <algorithm>
+
+
+using namespace wiesel;
+
+
+
+static void handle_startElement(void *user_data, const xmlChar *name, const xmlChar **attribs) {
+	XmlParser *parser = reinterpret_cast<XmlParser*>(user_data);
+	XmlParser::Attributes attribute_list;
+	std::string element = reinterpret_cast<const char*>(name);
+
+	// get all the attributes
+	while(attribs && attribs[0]) {
+		std::string attr_name  = reinterpret_cast<const char*>(attribs[0]);
+		std::string attr_value = reinterpret_cast<const char*>(attribs[1]);
+
+		attribute_list[attr_name] = attr_value;
+
+		attribs += 2;
+	}
+
+	// invoke callback
+	parser->startElement(element, attribute_list);
+
+	return;
+}
+
+
+static void handle_endElement(void *user_data, const xmlChar *name) {
+	XmlParser *parser = reinterpret_cast<XmlParser*>(user_data);
+	std::string element = reinterpret_cast<const char*>(name);
+
+	// invoke callback
+	parser->closeElement(element);
+
+	return;
+}
+
+
+static void handle_text(void *user_data, const xmlChar *chars, int len) {
+	XmlParser *parser = reinterpret_cast<XmlParser*>(user_data);
+	std::string text(reinterpret_cast<const char*>(chars), len);
+
+	// invoke callback
+	parser->addTextContent(text);
+
+	return;
+}
+
+
+
+static void init_sax_handler(xmlSAXHandler &handler) {
+	handler.startElement		= &handle_startElement;
+	handler.endElement			= &handle_endElement;
+	handler.characters			= &handle_text;
+
+	return;
+}
+
+
+
+LibXml2SaxParser::LibXml2SaxParser() {
+	return;
+}
+
+
+LibXml2SaxParser::~LibXml2SaxParser() {
+	return;
+}
+
+
+bool LibXml2SaxParser::parse(DataBuffer *buffer, XmlParserCallback *callback) {
+	assert(buffer);
+	if (buffer == NULL) {
+		return false;
+	}
+
+	LIBXML_TEST_VERSION
+	xmlSAXHandler handler = {0};
+	init_sax_handler(handler);
+
+	// create and initialize parser object
+	XmlParser *parser = new XmlParser(callback);
+	parser->retain();
+	parser->start();
+
+	// start parsing
+	int result = xmlSAXUserParseMemory(&handler, parser, buffer->getDataAsCharPtr(), buffer->getSize());
+
+	// parser cleanup
+	parser->finish();
+	safe_release(parser);
+
+	// libxml cleanup
+	xmlCleanupParser();
+	xmlMemoryDump();
+
+	return result == 0;
+}
+
+
+bool LibXml2SaxParser::parse(DataSource *source, XmlParserCallback *callback) {
+	FileDataSource *fds = dynamic_cast<FileDataSource*>(source);
+	if (fds) {
+		return parse(fds->getFile(), callback);
+	}
+	else {
+		DataBuffer *buffer = source->getDataBuffer();
+		if (buffer) {
+			return parse(buffer, callback);
+		}
+	}
+
+	return false;
+}
+
+
+bool LibXml2SaxParser::parse(File* file, XmlParserCallback *callback) {
+	std::string native_path = file->getNativePath();
+	if (native_path.empty() == false) {
+		LIBXML_TEST_VERSION
+		xmlSAXHandler handler = {0};
+		init_sax_handler(handler);
+
+		// create and initialize parser object
+		XmlParser *parser = new XmlParser(callback);
+		parser->retain();
+		parser->start();
+
+		// start parsing
+		int result = xmlSAXUserParseFile(&handler, parser, native_path.c_str());
+
+		// parser cleanup
+		parser->finish();
+		safe_release(parser);
+
+		// libxml cleanup
+		xmlCleanupParser();
+		xmlMemoryDump();
+
+		if (result == 0) {
+			return true;
+		}
+	}
+	
+	// when file parsing fails... there's still a DataBuffer...
+	DataBuffer *buffer = file->asDataSource()->getDataBuffer();
+	if (buffer) {
+		return parse(buffer, callback);
+	}
+
+	return false;
+}
+
+#endif /* WIESEL_SUPPORTS_LIBXML2 */

File src/common/wiesel/util/libxml_sax_parser.h

View file
+/**
+ * Copyright (C) 2012
+ * Christian Fischer
+ *
+ * https://bitbucket.org/baldur/wiesel/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+#ifndef __WIESEL_UTIL_LIBXML_SAX_PARSER_H__
+#define __WIESEL_UTIL_LIBXML_SAX_PARSER_H__
+
+#include <wiesel/wiesel-common.def>
+#include <wiesel/wiesel-common-config.h>
+
+#include <wiesel/util/xml_parser.h>
+
+
+#if WIESEL_SUPPORTS_LIBXML2
+
+namespace wiesel {
+
+	// predeclarations
+
+	class DataBuffer;
+	class DataSource;
+	class File;
+
+
+	class WIESEL_COMMON_EXPORT LibXml2SaxParser : public IXmlParser
+	{
+	public:
+		LibXml2SaxParser();
+		virtual ~LibXml2SaxParser();
+
+		/**
+		 * @brief Parse XML-Data from a DataBuffer object.
+		 * @param buffer	The DataBuffer to read from.
+		 * @param callback	A callback object which will receive the XML data.
+		 * @returns \c true on success.
+		 */
+		virtual bool parse(DataBuffer *buffer, XmlParserCallback *callback);
+
+		/**
+		 * @brief Parse XML-Data from a DataSource object.
+		 * @param source	The DataSource to read from.
+		 * @param callback	A callback object which will receive the XML data.
+		 * @returns \c true on success.
+		 */
+		virtual bool parse(DataSource *source, XmlParserCallback *callback);
+
+		/**
+		 * @brief Parse XML-Data from a File object..
+		 * @param file	The file to read from.
+		 * @param callback	A callback object which will receive the XML data.
+		 * @returns \c true on success.
+		 */
+		virtual bool parse(File *file, XmlParserCallback *callback);
+	};
+
+} /* namespace wiesel */
+#endif /* WIESEL_SUPPORTS_LIBXML2 */
+#endif /* __WIESEL_UTIL_LIBXML_SAX_PARSER_H__ */

File src/common/wiesel/util/libxml_sax_parser.loadable_module

View file
+
+#include <wiesel/module_registry.h>
+#include "libxml_sax_parser.h"
+
+#if WIESEL_SUPPORTS_LIBXML2
+
+	// add the module to the module registry
+	namespace wiesel {
+		REGISTER_MODULE_SINGLETON(
+				IXmlParser,
+				LibXml2SaxParser,
+				&generic_create<LibXml2SaxParser>,
+				"libXML2",
+				0x02080000u,
+				IModuleLoader::PriorityLow
+		)
+	}
+
+#endif // WIESEL_SUPPORTS_LIBXML2

File src/common/wiesel/wiesel-common-config.in

View file
 // enables support for libpng
 #cmakedefine01 WIESEL_SUPPORTS_LIBPNG
 
+// enables support for libxml2
+#cmakedefine01 WIESEL_SUPPORTS_LIBXML2
+
 
 #endif // __WIESEL_COMMON_CONFIG_H__

File src/core/wiesel/resources/graphics/spritesheet.cpp

View file
 };
 
 
-class SpriteSheetParser : public XmlSaxParser
+class SpriteSheetParser : public XmlParserCallback
 {
 public:
 	Directory*					parent_dir;
 	}
 
 public:
-	virtual void onElementStarted(const string &element, const Attributes &attributes) {
+	virtual void onDocumentStarted(const XmlDocumentState *docstate) {
+		return;
+	}
+
+	virtual void onDocumentFinished(const XmlDocumentState *docstate) {
+		return;
+	}
+
+	virtual void onElementStarted(const XmlDocumentState *docstate, const string &element, const XmlParser::Attributes &attributes) {
 		switch(state) {
 			case SpriteSheetParser_Null: {
 				if (element == "TextureAtlas") {
 					state = SpriteSheetParser_SimpleXml_TextureAtlas;
 
 					if (spritesheet == NULL) {
-						Attributes::const_iterator texture_path = attributes.find("imagePath");
+						XmlParser::Attributes::const_iterator texture_path = attributes.find("imagePath");
 						Texture *texture = NULL;
 
 						if (texture_path != attributes.end() && parent_dir) {
 			case SpriteSheetParser_SimpleXml_TextureAtlas: {
 				if (element == "sprite") {
 					if (spritesheet) {
-						SpriteFrame *sprite = parseSimpleXml_Sprite(attributes);
+						SpriteFrame *sprite = parseSimpleXml_Sprite(docstate, attributes);
 
 						if (sprite) {
 							spritesheet->add(sprite);
 		return;
 	}
 
-	virtual void onElementClosed(const string &element) {
+	virtual void onElementClosed(const XmlDocumentState *docstate, const string &element) {
 		switch(state) {
 			case SpriteSheetParser_SimpleXml_TextureAtlas: {
 				if (element == "TextureAtlas") {
 
 
 
-	SpriteFrame *parseSimpleXml_Sprite(const Attributes &attributes) {
+	SpriteFrame *parseSimpleXml_Sprite(const XmlDocumentState *docstate, const XmlParser::Attributes &attributes) {
 		string	sprite_name			= "";
 
 		// the actual coordinates within the texture which will result in texture coordinates
 
 		int		rotation			= 0;
 
-		for(Attributes::const_iterator it=attributes.begin(); it!=attributes.end(); it++) {
+		for(XmlParser::Attributes::const_iterator it=attributes.begin(); it!=attributes.end(); it++) {
 			if (it->first == "n") {
 				sprite_name = it->second;
 				continue;
 
 
 SpriteSheet *SpriteSheet::fromFile(File* file) {
-	SpriteSheetParser parser(file->getParent());
-	if (parser.parse(file)) {
-		return parser.spritesheet;
+	SpriteSheetParser *parser = new SpriteSheetParser(file->getParent());
+	SpriteSheet *result = NULL;
+	parser->retain();
+	
+	// start parsing the spritesheet
+	bool success = XmlParser::parse(file->asDataSource(), parser);
+
+	if (success) {
+		result = parser->spritesheet;
 	}
 
-	return NULL;
+	parser->release();
+
+	return result;
 }
 
 

File src/core/wiesel/util/xml_parser.cpp

View file
  * Boston, MA 02110-1301 USA
  */
 #include "xml_parser.h"
-#include "wiesel/io/datasource.h"
-#include "wiesel/io/file.h"
 
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlmemory.h>
-#include <libxml/xmlversion.h>
-
-#include <algorithm>
-
-
+#include <wiesel/io/datasource.h>
+#include <wiesel/io/file.h>
+#include <wiesel/module_registry.h>
 
 using namespace wiesel;
 
 
 
-struct ParserData {
-	XmlSaxParser				*callbacks;
-	XmlSaxParser::ElementStack	*stack;
-};
-
-
-static void handle_startElement(void *user_data, const xmlChar *name, const xmlChar **attribs) {
-	ParserData *parser = reinterpret_cast<ParserData*>(user_data);
-	XmlSaxParser::Attributes attribute_list;
-	std::string element = reinterpret_cast<const char*>(name);
-
-	// get all the attributes
-	while(attribs && attribs[0]) {
-		std::string attr_name  = reinterpret_cast<const char*>(attribs[0]);
-		std::string attr_value = reinterpret_cast<const char*>(attribs[1]);
-
-		attribute_list[attr_name] = attr_value;
-
-		attribs += 2;
-	}
-
-	// push the new element to the stack
-	parser->stack->push_back(element);
-
-	// invoke callback
-	parser->callbacks->onElementStarted(element, attribute_list);
-
+XmlParser::XmlParser() {
+	this->callback	= NULL;
+	this->state		= NULL;
 	return;
 }
 
 
-static void handle_endElement(void *user_data, const xmlChar *name) {
-	ParserData *parser = reinterpret_cast<ParserData*>(user_data);
-	std::string element = reinterpret_cast<const char*>(name);
+XmlParser::XmlParser(XmlParserCallback *callback) {
+	this->callback	= callback;
+	this->state		= NULL;
 
-	// does the element name match the stack?
-	assert(parser->stack->back() == element);
-
-	// invoke callback
-	parser->callbacks->onElementClosed(element);
-
-	// remove this element from the stack
-	if (parser->stack->size() && parser->stack->back() == element) {
-		parser->stack->pop_back();
+	assert(callback);
+	if (callback) {
+		callback->retain();
 	}
 
 	return;
 }
 
 
-static void handle_text(void *user_data, const xmlChar *chars, int len) {
-	ParserData *parser = reinterpret_cast<ParserData*>(user_data);
-	std::string text(reinterpret_cast<const char*>(chars), len);
+XmlParser::~XmlParser() {
+	assert(state == NULL); // parsing was not finished?
 
-	// invoke callback
-	parser->callbacks->onTextContent(text);
+	safe_release(callback);
+	safe_release(state);
 
 	return;
 }
 
 
+bool XmlParser::parse(DataSource *source, XmlParserCallback *callback) {
+	std::vector<ModuleLoader<IXmlParser>*> loaders = ModuleRegistry::getInstance()->findModules<IXmlParser>();
+	for(std::vector<ModuleLoader<IXmlParser>*>::iterator it=loaders.begin(); it!=loaders.end(); it++) {
+		IXmlParser *parser = (*it)->create();
 
-static void init_sax_handler(xmlSAXHandler &handler) {
-	handler.startElement		= &handle_startElement;
-	handler.endElement			= &handle_endElement;
-	handler.characters			= &handle_text;
-
-	return;
-}
-
-
-
-XmlSaxParser::XmlSaxParser() {
-	return;
-}
-
-
-XmlSaxParser::~XmlSaxParser() {
-	return;
-}
-
-
-bool XmlSaxParser::parse(DataBuffer *buffer) {
-	assert(buffer);
-	if (buffer == NULL) {
-		return false;
-	}
-
-	LIBXML_TEST_VERSION
-	clear();
-
-	ParserData parser_data = { this, &this->stack };
-	xmlSAXHandler handler = {0};
-	init_sax_handler(handler);
-
-	// start parsing
-	int result = xmlSAXUserParseMemory(&handler, &parser_data, buffer->getDataAsCharPtr(), buffer->getSize());
-
-	// cleanup
-	xmlCleanupParser();
-	xmlMemoryDump();
-
-	return result == 0;
-}
-
-
-bool XmlSaxParser::parse(DataSource *source) {
-	FileDataSource *fds = dynamic_cast<FileDataSource*>(source);
-	if (fds) {
-		return parse(fds->getFile());
-	}
-	else {
-		DataBuffer *buffer = source->getDataBuffer();
-		if (buffer) {
-			return parse(buffer);
+		if (parser) {
+			bool success = parser->parse(source, callback);
+			if (success) {
+				return true;
+			}
 		}
 	}
 
 }
 
 
-bool XmlSaxParser::parse(File* file) {
-	std::string native_path = file->getNativePath();
-	if (native_path.empty() == false) {
-		LIBXML_TEST_VERSION
-		clear();
+void XmlParser::start() {
+	assert(state == NULL); // last parsing was not finished?
 
-		ParserData parser_data = { this, &this->stack };
-		xmlSAXHandler handler = {0};
-		init_sax_handler(handler);
-
-		// start parsing
-		int result = xmlSAXUserParseFile(&handler, &parser_data, native_path.c_str());
-
-		// cleanup
-		xmlCleanupParser();
-		xmlMemoryDump();
-
-		if (result == 0) {
-			return true;
-		}
-	}
-	
-	// when file parsing fails... there's still a DataBuffer...
-	DataBuffer *buffer = file->asDataSource()->getDataBuffer();
-	if (buffer) {
-		return parse(buffer);
+	if (state) {
+		safe_release(state);
 	}
 
-	return false;
-}
+	state = new XmlDocumentState();
+	state->retain();
 
+	if (callback) {
+		callback->onDocumentStarted(state);
+	}
 
-void XmlSaxParser::clear() {
-	stack.clear();
-}
-
-
-void XmlSaxParser::onElementStarted(const std::string&, const Attributes&) {
 	return;
 }
 
-void XmlSaxParser::onElementClosed(const std::string&) {
+
+void XmlParser::finish() {
+	assert(state);					// parsing not started?
+	assert(state->stack.empty());	// mismatch between opening and closing tags?
+
+	if (state) {
+		if (callback) {
+			callback->onDocumentFinished(state);
+		}
+
+		safe_release(state);
+	}
+
 	return;
 }
 
-void XmlSaxParser::onTextContent(const std::string&) {
+
+void XmlParser::startElement(const std::string &element, const Attributes &attributes) {
+	assert(state);
+
+	if (state) {
+		state->stack.push_back(element);
+
+		if (callback) {
+			callback->onElementStarted(state, element, attributes);
+		}
+	}
+
 	return;
 }
 
+
+void XmlParser::closeElement(const std::string &element) {
+	assert(state);
+
+	if (state) {
+		assert(state->getCurrentElement() == element);
+
+		if (state->getCurrentElement() == element) {
+			state->stack.pop_back();
+		}
+
+		if (callback) {
+			callback->onElementClosed(state, element);
+		}
+	}
+
+	return;
+}
+
+
+void XmlParser::addTextContent(const std::string &text) {
+	assert(state);
+
+	if (state) {
+		if (callback) {
+			callback->onTextContent(state, text);
+		}
+	}
+
+	return;
+}
+
+
+
+
+
+XmlDocumentState::XmlDocumentState() {
+	return;
+}
+
+XmlDocumentState::~XmlDocumentState() {
+	return;
+}
+
+
+std::string XmlDocumentState::getCurrentElement() const {
+	if (stack.size()) {
+		return stack.back();
+	}
+
+	return "";
+}
+
+
+const XmlParser::ElementStack *XmlDocumentState::getElementStack() const {
+	return &stack;
+}
+
+
+
+
+IXmlParser::IXmlParser() {
+	return;
+}
+
+IXmlParser::~IXmlParser() {
+	return;
+}
+
+
+
+
+XmlParserCallback::XmlParserCallback() {
+	return;
+}
+
+XmlParserCallback::~XmlParserCallback() {
+	return;
+}
+
+void XmlParserCallback::onDocumentStarted(const XmlDocumentState*) {
+	return;
+}
+
+void XmlParserCallback::onDocumentFinished(const XmlDocumentState*) {
+	return;
+}
+
+void XmlParserCallback::onElementStarted(const XmlDocumentState*, const std::string&, const XmlParser::Attributes&) {
+	return;
+}
+
+void XmlParserCallback::onElementClosed(const XmlDocumentState*, const std::string&) {
+	return;
+}
+
+void XmlParserCallback::onTextContent(const XmlDocumentState*, const std::string&) {
+	return;
+}
+

File src/core/wiesel/util/xml_parser.h

View file
 
 #include <wiesel/wiesel-core.def>
 
+#include <wiesel/util/shared_object.h>
+#include <wiesel/module.h>
+
 #include <map>
 #include <string>
 #include <vector>
 
 	class DataBuffer;
 	class DataSource;
-	class File;
+
+	class XmlParser;
+	class XmlParserCallback;
+	class XmlDocumentState;
+
 
 
 	/**
 	 * @brief An utility class to create XML-Parsers for custom XML formats.
-	 * An implementation will extend this class and use the callback methods
-	 * to read the XML content.
 	 */
-	class WIESEL_CORE_EXPORT XmlSaxParser
+	class WIESEL_CORE_EXPORT XmlParser : public virtual SharedObject
 	{
 	public:
-		/**
-		 * @brief Creates a new parser object.
-		 */
-		XmlSaxParser();
+		/// an alias type for the stack containing all recent XML elements.
+		typedef std::vector<std::string>			ElementStack;
 
-		virtual ~XmlSaxParser();
+		/// an alias type for an element's attributes.
+		typedef std::map<std::string,std::string>	Attributes;
+
+	private:
+		XmlParser();
+
+	public:
+		XmlParser(XmlParserCallback *callback);
+		virtual ~XmlParser();
 
 	public:
 		/**
-		 * @brief Parse XML-Data from a DataBuffer object.
-		 * @param buffer	The DataBuffer to read from.
+		 * @brief Parse XML-Data from a DataSource object.
+		 * @param source	The DataSource to read from.
+		 * @param callback	A callback object which will receive the XML data.
 		 * @returns \c true on success.
 		 */
-		bool parse(DataBuffer *buffer);
+		static bool parse(DataSource *source, XmlParserCallback *callback);
+
+	public:
+		/// start parsing the xml data
+		void start();
+
+		/// finish parsing.
+		void finish();
+
+		/// a new XML element started.
+		void startElement(const std::string &element, const Attributes &attributes);
+
+		/// closes the current XML element. \c name should be the same as the top-level element.
+		void closeElement(const std::string &element);
+
+		/// add text content for the current XML element
+		void addTextContent(const std::string &text);
+
+	private:
+		XmlParserCallback*		callback;
+		XmlDocumentState*		state;
+	};
+
+
+
+	/**
+	 * @brief A module to implement an XML parser,
+	 * which sends its results to the given callback object.
+	 */
+	class WIESEL_CORE_EXPORT IXmlParser : public Module
+	{
+	public:
+		IXmlParser();
+		virtual ~IXmlParser();
 
 		/**
 		 * @brief Parse XML-Data from a DataSource object.
 		 * @param source	The DataSource to read from.
+		 * @param callback	A callback object which will receive the XML data.
 		 * @returns \c true on success.
 		 */
-		bool parse(DataSource *source);
+		virtual bool parse(DataSource *source, XmlParserCallback *callback) = 0;
+	};
 
-		/**
-		 * @brief Parse XML-Data from a File object..
-		 * @param file	The file to read from.
-		 * @returns \c true on success.
-		 */
-		bool parse(File *file);
+
+
+	/**
+	 * @brief An object which stores the current state of a document during parsing.
+	 */
+	class WIESEL_CORE_EXPORT XmlDocumentState : public virtual SharedObject
+	{
+	friend class XmlParser;
+
+	public:
+		XmlDocumentState();
+		virtual ~XmlDocumentState();
+
+	public:
+
+	public:
+		/// get the tag-name of the current XML element.
+		std::string getCurrentElement() const;
+
+		/// get the stack with the current XML element and all of it's parents.
+		const XmlParser::ElementStack *getElementStack() const;
+
+	private:
+		XmlParser::ElementStack			stack;
+	};
+
+
+
+	/**
+	 * @brief The callback class to implement a parser for custom XML formats.
+	 * An implementation will extend this class and use the callback methods
+	 * to read the XML content.
+	 */
+	class WIESEL_CORE_EXPORT XmlParserCallback : public virtual SharedObject
+	{
+	protected:
+		XmlParserCallback();
+
+	public:
+		virtual ~XmlParserCallback();
 
 	protected:
 		/**
 
 	// SAX handler callbacks
 	public:
-		/// an alias type for an element's attributes.
-		typedef std::map<std::string,std::string>	Attributes;
+		/**
+		 * @brief Started parsing a new XML Document.
+		 * @param state			The state of the new XML document.
+		 */
+		virtual void onDocumentStarted(const XmlDocumentState *state);
 
-		/// an alias type for the stack containing all recent XML elements.
-		typedef std::vector<std::string>			ElementStack;
+		/**
+		 * @brief Parsing the current document has been finished.
+		 * @param state			The state of the new XML document.
+		 */
+		virtual void onDocumentFinished(const XmlDocumentState *state);
 
 		/**
 		 * @brief A new XML element hast started. Will be followed by an onElementClosed event.
+		 * @param state			The current state of the parsed XML document.
 		 * @param element		The name of the closed element.
 		 * @param attributes	A list containing all attributes of this element.
 		 */
-		virtual void onElementStarted(const std::string &element, const Attributes &attributes);
+		virtual void onElementStarted(const XmlDocumentState *state, const std::string &element, const XmlParser::Attributes &attributes);
 
 		/**
 		 * @brief A previously started element was closed.
+		 * @param state			The current state of the parsed XML document.
 		 * @param element		The name of the closed element.
 		 */
-		virtual void onElementClosed(const std::string &element);
+		virtual void onElementClosed(const XmlDocumentState *state, const std::string &element);
 
 		/**
 		 * @brief Delivers the text-content of the current element.
+		 * @param state			The current state of the parsed XML document.
 		 * @param text			The current element's text content.
 		 */
-		virtual void onTextContent(const std::string &text);
-
-	public:
-		const ElementStack *getElementStack() const;
-
-	private:
-		ElementStack	stack;
+		virtual void onTextContent(const XmlDocumentState *state, const std::string &text);
 	};
 
 } /* namespace wiesel */