[aravis/dom: 1/5] dom: initial import from lasem.



commit 75a73c5bc5d1847532a66c44b736ffaf15d03ce0
Author: Emmanuel Pacaud <emmanuel gnome org>
Date:   Sun Feb 19 17:52:44 2012 +0100

    dom: initial import from lasem.

 src/lsmdom.h                 |   42 +++
 src/lsmdomcharacterdata.c    |  114 +++++++
 src/lsmdomcharacterdata.h    |   59 ++++
 src/lsmdomdocument.c         |  244 +++++++++++++++
 src/lsmdomdocument.h         |   82 +++++
 src/lsmdomdocumentfragment.c |   81 +++++
 src/lsmdomdocumentfragment.h |   55 ++++
 src/lsmdomelement.c          |  124 ++++++++
 src/lsmdomelement.h          |   62 ++++
 src/lsmdomenumtypes.c        |   99 ++++++
 src/lsmdomenumtypes.h        |   26 ++
 src/lsmdomimplementation.c   |   73 +++++
 src/lsmdomimplementation.h   |   43 +++
 src/lsmdomnamednodemap.c     |   81 +++++
 src/lsmdomnamednodemap.h     |   64 ++++
 src/lsmdomnode.c             |  672 ++++++++++++++++++++++++++++++++++++++++++
 src/lsmdomnode.h             |  120 ++++++++
 src/lsmdomnodelist.c         |   57 ++++
 src/lsmdomnodelist.h         |   58 ++++
 src/lsmdomparser.c           |  423 ++++++++++++++++++++++++++
 src/lsmdomparser.h           |   52 ++++
 src/lsmdomtext.c             |   82 +++++
 src/lsmdomtext.h             |   55 ++++
 src/lsmdomtypes.h            |   44 +++
 24 files changed, 2812 insertions(+), 0 deletions(-)
---
diff --git a/src/lsmdom.h b/src/lsmdom.h
new file mode 100644
index 0000000..71c7515
--- /dev/null
+++ b/src/lsmdom.h
@@ -0,0 +1,42 @@
+/* Lasem
+ *
+ * Copyright  2007-2008 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_DOM_H
+#define LSM_DOM_H
+
+#include <lsm.h>
+
+#include <lsmdomtypes.h>
+
+#include <lsmdomnode.h>
+#include <lsmdomnodelist.h>
+#include <lsmdomdocument.h>
+#include <lsmdomelement.h>
+#include <lsmdomcharacterdata.h>
+#include <lsmdomtext.h>
+#include <lsmdomimplementation.h>
+
+#include <lsmdomparser.h>
+#include <lsmdomview.h>
+
+#endif
diff --git a/src/lsmdomcharacterdata.c b/src/lsmdomcharacterdata.c
new file mode 100644
index 0000000..69c1876
--- /dev/null
+++ b/src/lsmdomcharacterdata.c
@@ -0,0 +1,114 @@
+/* Lasem
+ *
+ * Copyright  2007-2010 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+/**
+ * SECTION:lsmdomcharacterdata
+ * @short_description: Base class for DOM character data nodes
+ */
+
+#include <lsmdomcharacterdata.h>
+#include <lsmdebug.h>
+#include <string.h>
+
+static GObjectClass *parent_class = NULL;
+
+/* LsmDomNode implementation */
+
+static void
+lsm_dom_character_data_write_to_stream (LsmDomNode *self, GOutputStream *stream, GError **error)
+{
+	LsmDomCharacterData *character_data = LSM_DOM_CHARACTER_DATA (self);
+
+	if (character_data->data != NULL)
+		g_output_stream_write (stream, character_data->data, strlen (character_data->data), NULL, error);
+}
+
+static const char *
+lsm_dom_character_data_get_node_value (LsmDomNode* self)
+{
+	return lsm_dom_character_data_get_data (LSM_DOM_CHARACTER_DATA (self));
+}
+
+static void
+lsm_dom_character_data_set_node_value (LsmDomNode* self, const char *value)
+{
+	lsm_dom_character_data_set_data (LSM_DOM_CHARACTER_DATA (self), value);
+}
+
+/* LsmDomCharacterData implementation */
+
+const char *
+lsm_dom_character_data_get_data (LsmDomCharacterData* self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_CHARACTER_DATA (self), NULL);
+
+	return self->data;
+}
+
+void
+lsm_dom_character_data_set_data (LsmDomCharacterData* self, const char * value)
+{
+	g_return_if_fail (LSM_IS_DOM_CHARACTER_DATA (self));
+	g_return_if_fail (value != NULL);
+
+	g_free (self->data);
+	self->data = g_strdup (value);
+
+	lsm_debug_dom ("[LsmDomCharacterData::set_data] Value = '%s'", value);
+
+	lsm_dom_node_changed (LSM_DOM_NODE (self));
+}
+
+static void
+lsm_dom_character_data_init (LsmDomCharacterData *character_data)
+{
+}
+
+static void
+lsm_dom_character_data_finalize (GObject *object)
+{
+	LsmDomCharacterData *self = LSM_DOM_CHARACTER_DATA (object);
+
+	g_free (self->data);
+
+	parent_class->finalize (object);
+}
+
+/* LsmDomCharacterData class */
+
+static void
+lsm_dom_character_data_class_init (LsmDomCharacterDataClass *character_data_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (character_data_class);
+	LsmDomNodeClass *node_class = LSM_DOM_NODE_CLASS (character_data_class);
+
+	parent_class = g_type_class_peek_parent (character_data_class);
+
+	object_class->finalize = lsm_dom_character_data_finalize;
+
+	node_class->write_to_stream = lsm_dom_character_data_write_to_stream;
+	node_class->set_node_value = lsm_dom_character_data_set_node_value;
+	node_class->get_node_value = lsm_dom_character_data_get_node_value;
+}
+
+G_DEFINE_ABSTRACT_TYPE (LsmDomCharacterData, lsm_dom_character_data, LSM_TYPE_DOM_NODE)
diff --git a/src/lsmdomcharacterdata.h b/src/lsmdomcharacterdata.h
new file mode 100644
index 0000000..2abedb1
--- /dev/null
+++ b/src/lsmdomcharacterdata.h
@@ -0,0 +1,59 @@
+/* Lasem
+ *
+ * Copyright  2007-2010 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_DOM_CHARACTER_DATA_H
+#define LSM_DOM_CHARACTER_DATA_H
+
+#include <lsmdomnode.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_DOM_CHARACTER_DATA             (lsm_dom_character_data_get_type ())
+#define LSM_DOM_CHARACTER_DATA(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_DOM_CHARACTER_DATA, LsmDomCharacterData))
+#define LSM_DOM_CHARACTER_DATA_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_DOM_CHARACTER_DATA, LsmDomNodeClass))
+#define LSM_IS_DOM_CHARACTER_DATA(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_DOM_CHARACTER_DATA))
+#define LSM_IS_DOM_CHARACTER_DATA_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_DOM_CHARACTER_DATA))
+#define LSM_DOM_CHARACTER_DATA_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_DOM_CHARACTER_DATA, LsmDomCharacterDataClass))
+
+typedef struct _LsmDomCharacterDataClass LsmDomCharacterDataClass;
+
+struct _LsmDomCharacterData
+{
+	LsmDomNode node;
+
+	char *data;
+};
+
+struct _LsmDomCharacterDataClass {
+	LsmDomNodeClass parent_class;
+};
+
+GType lsm_dom_character_data_get_type (void);
+
+const char * 	lsm_dom_character_data_get_data 	(LsmDomCharacterData* self);
+void 		lsm_dom_character_data_set_data 	(LsmDomCharacterData* self, const char* value);
+
+G_END_DECLS
+
+#endif
+
diff --git a/src/lsmdomdocument.c b/src/lsmdomdocument.c
new file mode 100644
index 0000000..e340e3d
--- /dev/null
+++ b/src/lsmdomdocument.c
@@ -0,0 +1,244 @@
+/* Lasem
+ *
+ * Copyright  2007-2010 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+/**
+ * SECTION:lsmdomdocument
+ * @short_description: Base class for DOM document nodes
+ */
+
+#include <lsmdomdocument.h>
+#include <lsmdomelement.h>
+#include <lsmstr.h>
+#include <lsmdebug.h>
+#include <lsmdomtext.h>
+#include <gio/gio.h>
+#include <string.h>
+
+static GObjectClass *parent_class;
+
+/* LsmDomNode implementation */
+
+static const char *
+lsm_dom_document_get_node_name (LsmDomNode *node)
+{
+	return "#document";
+}
+
+static LsmDomNodeType
+lsm_dom_document_get_node_type (LsmDomNode *node)
+{
+	return LSM_DOM_NODE_TYPE_DOCUMENT_NODE;
+}
+
+/* LsmDomDocument implementation */
+
+LsmDomElement *
+lsm_dom_document_get_document_element (LsmDomDocument *self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_DOCUMENT (self), NULL);
+
+	return LSM_DOM_ELEMENT (lsm_dom_node_get_first_child (LSM_DOM_NODE (self)));
+}
+
+LsmDomElement *
+lsm_dom_document_create_element (LsmDomDocument *document, const char *tag_name)
+{
+	LsmDomDocumentClass *document_class;
+
+	g_return_val_if_fail (LSM_IS_DOM_DOCUMENT (document), NULL);
+
+	document_class = LSM_DOM_DOCUMENT_GET_CLASS (document);
+	if (document_class->create_element != NULL)
+		return document_class->create_element (document, tag_name);
+
+	return NULL;
+}
+
+LsmDomText *
+lsm_dom_document_create_text_node_base (LsmDomDocument *document, const char *data)
+{
+	return LSM_DOM_TEXT (lsm_dom_text_new (data));
+}
+
+LsmDomText *
+lsm_dom_document_create_text_node (LsmDomDocument *document, const char *data)
+{
+	g_return_val_if_fail (LSM_IS_DOM_DOCUMENT (document), NULL);
+
+	return LSM_DOM_DOCUMENT_GET_CLASS (document)->create_text_node (document, data);
+}
+
+LsmDomView *
+lsm_dom_document_create_view (LsmDomDocument *self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_DOCUMENT (self), NULL);
+
+	return LSM_DOM_DOCUMENT_GET_CLASS (self)->create_view (self);
+}
+
+LsmDomElement *
+lsm_dom_document_get_element_by_id (LsmDomDocument *self, const char *id)
+{
+	g_return_val_if_fail (LSM_IS_DOM_DOCUMENT (self), NULL);
+	g_return_val_if_fail (id != NULL, NULL);
+
+	lsm_debug_dom ("[LsmDomDocument::get_element_by_id] Lookup '%s'", id);
+
+	return g_hash_table_lookup (self->ids, id);
+}
+
+void
+lsm_dom_document_register_element (LsmDomDocument *self, LsmDomElement *element, const char *id)
+{
+	char *old_id;
+
+	g_return_if_fail (LSM_IS_DOM_DOCUMENT (self));
+
+	old_id = g_hash_table_lookup (self->elements, element);
+	if (old_id != NULL) {
+		lsm_debug_dom ("[LsmDomDocument::register_element] Unregister '%s'", old_id);
+
+		g_hash_table_remove (self->elements, element);
+		g_hash_table_remove (self->ids, old_id);
+	}
+
+	if (id != NULL) {
+		char *new_id = g_strdup (id);
+
+		lsm_debug_dom ("[LsmDomDocument::register_element] Register '%s'", id);
+
+		g_hash_table_replace (self->ids, new_id, element);
+		g_hash_table_replace (self->elements, element, new_id);
+	}
+}
+
+const char *
+lsm_dom_document_get_url (LsmDomDocument *self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_DOCUMENT (self), NULL);
+
+	return self->url;
+}
+
+void
+lsm_dom_document_set_path (LsmDomDocument *self, const char *path)
+{
+	g_return_if_fail (LSM_IS_DOM_DOCUMENT (self));
+
+	g_free (self->url);
+
+	if (path == NULL) {
+		self->url = NULL;
+		return;
+	}
+
+	self->url = lsm_str_to_uri (path);
+}
+
+void
+lsm_dom_document_set_url (LsmDomDocument *self, const char *url)
+{
+	g_return_if_fail (LSM_IS_DOM_DOCUMENT (self));
+	g_return_if_fail (url == NULL || lsm_str_is_uri (url));
+
+	g_free (self->url);
+	self->url = g_strdup (url);
+}
+
+void *
+lsm_dom_document_get_href_data (LsmDomDocument *self, const char *href, gsize *size)
+{
+	GFile *file;
+	char *data = NULL;
+
+	g_return_val_if_fail (LSM_IS_DOM_DOCUMENT (self), NULL);
+	g_return_val_if_fail (href != NULL, NULL);
+
+	if (strncmp (href, "data:", 5) == 0) {
+		while (*href != '\0' && *href != ',')
+			href++;
+		return g_base64_decode (href, size);
+	}
+
+	file = g_file_new_for_uri (href);
+
+	if (!g_file_load_contents (file, NULL, &data, size, NULL, NULL) && self->url != NULL) {
+		GFile *document_file;
+		GFile *parent_file;
+
+		g_object_unref (file);
+
+		document_file = g_file_new_for_uri (self->url);
+		parent_file = g_file_get_parent (document_file);
+		file = g_file_resolve_relative_path (parent_file, href);
+		g_object_unref (document_file);
+		g_object_unref (parent_file);
+
+		g_file_load_contents (file, NULL, &data, size, NULL, NULL);
+	}
+
+	g_object_unref (file);
+
+	return data;
+}
+
+static void
+lsm_dom_document_init (LsmDomDocument *document)
+{
+	document->ids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	document->elements = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+}
+
+static void
+lsm_dom_document_finalize (GObject *object)
+{
+	LsmDomDocument *document = LSM_DOM_DOCUMENT (object);
+
+	g_hash_table_unref (document->elements);
+	g_hash_table_unref (document->ids);
+
+	g_free (document->url);
+
+	parent_class->finalize (object);
+}
+
+/* LsmDomDocument class */
+
+static void
+lsm_dom_document_class_init (LsmDomDocumentClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	LsmDomNodeClass *node_class = LSM_DOM_NODE_CLASS (klass);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	object_class->finalize = lsm_dom_document_finalize;
+
+	node_class->get_node_name = lsm_dom_document_get_node_name;
+	node_class->get_node_type = lsm_dom_document_get_node_type;
+
+	klass->create_text_node = lsm_dom_document_create_text_node_base;
+}
+
+G_DEFINE_ABSTRACT_TYPE (LsmDomDocument, lsm_dom_document, LSM_TYPE_DOM_NODE)
+
diff --git a/src/lsmdomdocument.h b/src/lsmdomdocument.h
new file mode 100644
index 0000000..597631a
--- /dev/null
+++ b/src/lsmdomdocument.h
@@ -0,0 +1,82 @@
+/* Lasem
+ *
+ * Copyright  2007-2008 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_DOM_DOCUMENT_H
+#define LSM_DOM_DOCUMENT_H
+
+#include <lsmtypes.h>
+#include <lsmdomtypes.h>
+#include <lsmdomnode.h>
+#include <lsmdomview.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_DOM_DOCUMENT             (lsm_dom_document_get_type ())
+#define LSM_DOM_DOCUMENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_DOM_DOCUMENT, LsmDomDocument))
+#define LSM_DOM_DOCUMENT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_DOM_DOCUMENT, LsmDomDocumentClass))
+#define LSM_IS_DOM_DOCUMENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_DOM_DOCUMENT))
+#define LSM_IS_DOM_DOCUMENT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_DOM_DOCUMENT))
+#define LSM_DOM_DOCUMENT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_DOM_DOCUMENT, LsmDomDocumentClass))
+
+typedef struct _LsmDomDocumentClass LsmDomDocumentClass;
+
+struct _LsmDomDocument {
+	LsmDomNode node;
+
+	GHashTable *	ids;
+	GHashTable *	elements;
+
+	char *		url;
+
+};
+
+struct _LsmDomDocumentClass {
+	LsmDomNodeClass parent_class;
+
+	LsmDomElement *	(*get_document_element) (LsmDomDocument* self);
+	LsmDomElement *	(*create_element) 	(LsmDomDocument* self, const char *tag_name);
+	LsmDomText * 	(*create_text_node) 	(LsmDomDocument* self, const char *data);
+
+	LsmDomView*	(*create_view) 		(LsmDomDocument *self);
+};
+
+GType lsm_dom_document_get_type (void);
+
+LsmDomElement* 	lsm_dom_document_get_document_element 	(LsmDomDocument* self);
+LsmDomElement* 	lsm_dom_document_create_element 	(LsmDomDocument* self, const char *tag_name);
+LsmDomText* 	lsm_dom_document_create_text_node 	(LsmDomDocument* self, const char *data);
+LsmDomElement *	lsm_dom_document_get_element_by_id 	(LsmDomDocument *self, const char *id);
+
+void 		lsm_dom_document_register_element 	(LsmDomDocument *self, LsmDomElement *element, const char *id);
+
+LsmDomView*	lsm_dom_document_create_view		(LsmDomDocument *self);
+
+const char * 	lsm_dom_document_get_url 		(LsmDomDocument *self);
+void		lsm_dom_document_set_url		(LsmDomDocument *self, const char *url);
+void 		lsm_dom_document_set_path 		(LsmDomDocument *self, const char *path);
+
+void * 		lsm_dom_document_get_href_data 		(LsmDomDocument *self, const char *href, gsize *size);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmdomdocumentfragment.c b/src/lsmdomdocumentfragment.c
new file mode 100644
index 0000000..297db5b
--- /dev/null
+++ b/src/lsmdomdocumentfragment.c
@@ -0,0 +1,81 @@
+/* Lasem
+ *
+ * Copyright  2010 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+/**
+ * SECTION:lsmdomdocumentfragment
+ * @short_description: Base class for DOM document fragments
+ */
+
+#include <lsmdomdocumentfragment.h>
+#include <string.h>
+
+static GObjectClass *parent_class = NULL;
+
+/* LsmDomNode implementation */
+
+static const char *
+lsm_dom_document_fragment_get_node_name (LsmDomNode *node)
+{
+	return "#document-fragment";
+}
+
+static const char *
+lsm_dom_document_fragment_get_node_value (LsmDomNode *node)
+{
+	return NULL;
+}
+
+static LsmDomNodeType
+lsm_dom_document_fragment_get_node_type (LsmDomNode *node)
+{
+	return LSM_DOM_NODE_TYPE_DOCUMENT_FRAGMENT_NODE;
+}
+
+/* LsmDomDocumentFragment implementation */
+
+LsmDomDocumentFragment *
+lsm_dom_document_fragment_new (void)
+{
+	return g_object_new (LSM_TYPE_DOM_DOCUMENT_FRAGMENT, NULL);
+}
+
+static void
+lsm_dom_document_fragment_init (LsmDomDocumentFragment *document_fragment)
+{
+}
+
+/* LsmDomDocumentFragment class */
+
+static void
+lsm_dom_document_fragment_class_init (LsmDomDocumentFragmentClass *klass)
+{
+	LsmDomNodeClass *node_class = LSM_DOM_NODE_CLASS (klass);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	node_class->get_node_name = lsm_dom_document_fragment_get_node_name;
+	node_class->get_node_value = lsm_dom_document_fragment_get_node_value;
+	node_class->get_node_type = lsm_dom_document_fragment_get_node_type;
+}
+
+G_DEFINE_ABSTRACT_TYPE (LsmDomDocumentFragment, lsm_dom_document_fragment, LSM_TYPE_DOM_NODE)
diff --git a/src/lsmdomdocumentfragment.h b/src/lsmdomdocumentfragment.h
new file mode 100644
index 0000000..4a7d4c6
--- /dev/null
+++ b/src/lsmdomdocumentfragment.h
@@ -0,0 +1,55 @@
+/* Lasem
+ *
+ * Copyright  2010 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_DOM_DOCUMENT_FRAGMENT_H
+#define LSM_DOM_DOCUMENT_FRAGMENT_H
+
+#include <lsmdom.h>
+#include <lsmdomnode.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_DOM_DOCUMENT_FRAGMENT             (lsm_dom_document_fragment_get_type ())
+#define LSM_DOM_DOCUMENT_FRAGMENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_DOM_DOCUMENT_FRAGMENT, LsmDomDocumentFragment))
+#define LSM_DOM_DOCUMENT_FRAGMENT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_DOM_DOCUMENT_FRAGMENT, LsmDomDocumentFragmentClass))
+#define LSM_IS_DOM_DOCUMENT_FRAGMENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_DOM_DOCUMENT_FRAGMENT))
+#define LSM_IS_DOM_DOCUMENT_FRAGMENT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_DOM_DOCUMENT_FRAGMENT))
+#define LSM_DOM_DOCUMENT_FRAGMENT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_DOM_DOCUMENT_FRAGMENT, LsmDomDocumentFragmentClass))
+
+typedef struct _LsmDomDocumentFragmentClass LsmDomDocumentFragmentClass;
+
+struct _LsmDomDocumentFragment {
+	LsmDomNode node;
+};
+
+struct _LsmDomDocumentFragmentClass {
+	LsmDomNodeClass parent_class;
+};
+
+GType lsm_dom_document_fragment_get_type (void);
+
+LsmDomDocumentFragment * 	lsm_dom_document_fragment_new 		(void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmdomelement.c b/src/lsmdomelement.c
new file mode 100644
index 0000000..bc3be95
--- /dev/null
+++ b/src/lsmdomelement.c
@@ -0,0 +1,124 @@
+/* Lasem
+ *
+ * Copyright  2007-2008 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+/**
+ * SECTION:lsmdomelement
+ * @short_description: Base class for DOM element nodes
+ */
+
+#include <lsmdomelement.h>
+#include <string.h>
+
+static GObjectClass *parent_class = NULL;
+
+/* LsmDomNode implementation */
+
+static const char *
+lsm_dom_element_get_node_value (LsmDomNode *node)
+{
+	return NULL;
+}
+
+static LsmDomNodeType
+lsm_dom_element_get_node_type (LsmDomNode *node)
+{
+	return LSM_DOM_NODE_TYPE_ELEMENT_NODE;
+}
+
+static void
+lsm_dom_element_write_to_stream (LsmDomNode *self, GOutputStream *stream, GError **error)
+{
+	LsmDomElementClass *element_class;
+	char *string;
+	char *attributes = NULL;
+
+	element_class = LSM_DOM_ELEMENT_GET_CLASS (self);
+	if (element_class->get_serialized_attributes != NULL)
+		attributes = element_class->get_serialized_attributes (LSM_DOM_ELEMENT (self));
+
+	if (attributes != NULL)
+		string = g_strdup_printf ("<%s %s>", lsm_dom_node_get_node_name (self), attributes);
+	else
+		string = g_strdup_printf ("<%s>", lsm_dom_node_get_node_name (self));
+
+	g_output_stream_write (stream, string, strlen (string), NULL, error);
+	g_free (string);
+	g_free (attributes);
+
+	LSM_DOM_NODE_CLASS (parent_class)->write_to_stream (self, stream, error);
+
+	string = g_strdup_printf ("</\%s>\n", lsm_dom_node_get_node_name (self));
+	g_output_stream_write (stream, string, strlen (string), NULL, error);
+	g_free (string);
+}
+
+/* LsmDomElement implementation */
+
+const char *
+lsm_dom_element_get_attribute (LsmDomElement* self, const char* name)
+{
+	g_return_val_if_fail (LSM_IS_DOM_ELEMENT (self), NULL);
+	g_return_val_if_fail (name != NULL, NULL);
+
+	return LSM_DOM_ELEMENT_GET_CLASS (self)->get_attribute (self, name);
+}
+
+void
+lsm_dom_element_set_attribute (LsmDomElement* self, const char* name, const char* attribute_value)
+{
+	g_return_if_fail (LSM_IS_DOM_ELEMENT (self));
+	g_return_if_fail (name != NULL);
+
+	LSM_DOM_ELEMENT_GET_CLASS (self)->set_attribute (self, name, attribute_value);
+
+	lsm_dom_node_changed (LSM_DOM_NODE (self));
+}
+
+const char *
+lsm_dom_element_get_tag_name (LsmDomElement *self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_ELEMENT (self), NULL);
+
+	return lsm_dom_node_get_node_name (LSM_DOM_NODE (self));
+}
+
+static void
+lsm_dom_element_init (LsmDomElement *element)
+{
+}
+
+/* LsmDomElement class */
+
+static void
+lsm_dom_element_class_init (LsmDomElementClass *klass)
+{
+	LsmDomNodeClass *node_class = LSM_DOM_NODE_CLASS (klass);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	node_class->get_node_value = lsm_dom_element_get_node_value;
+	node_class->get_node_type = lsm_dom_element_get_node_type;
+	node_class->write_to_stream = lsm_dom_element_write_to_stream;
+}
+
+G_DEFINE_ABSTRACT_TYPE (LsmDomElement, lsm_dom_element, LSM_TYPE_DOM_NODE)
diff --git a/src/lsmdomelement.h b/src/lsmdomelement.h
new file mode 100644
index 0000000..1ede041
--- /dev/null
+++ b/src/lsmdomelement.h
@@ -0,0 +1,62 @@
+/* Lasem
+ *
+ * Copyright  2007-2008 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_DOM_ELEMENT_H
+#define LSM_DOM_ELEMENT_H
+
+#include <lsmdom.h>
+#include <lsmdomnode.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_DOM_ELEMENT             (lsm_dom_element_get_type ())
+#define LSM_DOM_ELEMENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_DOM_ELEMENT, LsmDomElement))
+#define LSM_DOM_ELEMENT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_DOM_ELEMENT, LsmDomElementClass))
+#define LSM_IS_DOM_ELEMENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_DOM_ELEMENT))
+#define LSM_IS_DOM_ELEMENT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_DOM_ELEMENT))
+#define LSM_DOM_ELEMENT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_DOM_ELEMENT, LsmDomElementClass))
+
+typedef struct _LsmDomElementClass LsmDomElementClass;
+
+struct _LsmDomElement {
+	LsmDomNode node;
+};
+
+struct _LsmDomElementClass {
+	LsmDomNodeClass parent_class;
+
+	const char* 	(*get_attribute) (LsmDomElement *self, const char *name);
+	void 		(*set_attribute) (LsmDomElement *self, const char *name, const char *attribute_value);
+	char *		(*get_serialized_attributes)	(LsmDomElement *self);
+};
+
+GType lsm_dom_element_get_type (void);
+
+const char * 	lsm_dom_element_get_tag_name 	(LsmDomElement *self);
+const char* 	lsm_dom_element_get_attribute 	(LsmDomElement* self, const char* name);
+void 		lsm_dom_element_set_attribute 	(LsmDomElement* self, const char* name, const char* attribute_value);
+
+G_END_DECLS
+
+#endif
+
diff --git a/src/lsmdomenumtypes.c b/src/lsmdomenumtypes.c
new file mode 100644
index 0000000..95c5d42
--- /dev/null
+++ b/src/lsmdomenumtypes.c
@@ -0,0 +1,99 @@
+
+/* Generated data (by glib-mkenums) */
+
+#include "lsmdomenumtypes.h"
+
+/* enumerations from "lsmdebug.h" */
+#include "lsmdebug.h"
+
+GType
+lsm_debug_level_get_type (void)
+{
+	static GType the_type = 0;
+
+	if (the_type == 0)
+	{
+		static const GEnumValue values[] = {
+			{ LSM_DEBUG_LEVEL_NONE,
+			  "LSM_DEBUG_LEVEL_NONE",
+			  "none" },
+			{ LSM_DEBUG_LEVEL_WARNING,
+			  "LSM_DEBUG_LEVEL_WARNING",
+			  "warning" },
+			{ LSM_DEBUG_LEVEL_DEBUG,
+			  "LSM_DEBUG_LEVEL_DEBUG",
+			  "debug" },
+			{ LSM_DEBUG_LEVEL_LOG,
+			  "LSM_DEBUG_LEVEL_LOG",
+			  "log" },
+			{ LSM_DEBUG_LEVEL_COUNT,
+			  "LSM_DEBUG_LEVEL_COUNT",
+			  "count" },
+			{ 0, NULL, NULL }
+		};
+		the_type = g_enum_register_static (
+				g_intern_static_string ("LsmDebugLevel"),
+				values);
+	}
+	return the_type;
+}
+
+/* enumerations from "lsmdomnode.h" */
+#include "lsmdomnode.h"
+
+GType
+lsm_dom_node_type_get_type (void)
+{
+	static GType the_type = 0;
+
+	if (the_type == 0)
+	{
+		static const GEnumValue values[] = {
+			{ LSM_DOM_NODE_TYPE_ELEMENT_NODE,
+			  "LSM_DOM_NODE_TYPE_ELEMENT_NODE",
+			  "element-node" },
+			{ LSM_DOM_NODE_TYPE_ATTRIBUTE_NODE,
+			  "LSM_DOM_NODE_TYPE_ATTRIBUTE_NODE",
+			  "attribute-node" },
+			{ LSM_DOM_NODE_TYPE_TEXT_NODE,
+			  "LSM_DOM_NODE_TYPE_TEXT_NODE",
+			  "text-node" },
+			{ LSM_DOM_NODE_TYPE_CDATA_SECTION_NODE,
+			  "LSM_DOM_NODE_TYPE_CDATA_SECTION_NODE",
+			  "cdata-section-node" },
+			{ LSM_DOM_NODE_TYPE_ENTITY_REFERENCE_NODE,
+			  "LSM_DOM_NODE_TYPE_ENTITY_REFERENCE_NODE",
+			  "entity-reference-node" },
+			{ LSM_DOM_NODE_TYPE_ENTITY_NODE,
+			  "LSM_DOM_NODE_TYPE_ENTITY_NODE",
+			  "entity-node" },
+			{ LSM_DOM_NODE_TYPE_PROCESSING_INSTRUCTION_NODE,
+			  "LSM_DOM_NODE_TYPE_PROCESSING_INSTRUCTION_NODE",
+			  "processing-instruction-node" },
+			{ LSM_DOM_NODE_TYPE_COMMENT_NODE,
+			  "LSM_DOM_NODE_TYPE_COMMENT_NODE",
+			  "comment-node" },
+			{ LSM_DOM_NODE_TYPE_DOCUMENT_NODE,
+			  "LSM_DOM_NODE_TYPE_DOCUMENT_NODE",
+			  "document-node" },
+			{ LSM_DOM_NODE_TYPE_DOCUMENT_TYPE_NODE,
+			  "LSM_DOM_NODE_TYPE_DOCUMENT_TYPE_NODE",
+			  "document-type-node" },
+			{ LSM_DOM_NODE_TYPE_DOCUMENT_FRAGMENT_NODE,
+			  "LSM_DOM_NODE_TYPE_DOCUMENT_FRAGMENT_NODE",
+			  "document-fragment-node" },
+			{ LSM_DOM_NODE_TYPE_NOTATION_NODE,
+			  "LSM_DOM_NODE_TYPE_NOTATION_NODE",
+			  "notation-node" },
+			{ 0, NULL, NULL }
+		};
+		the_type = g_enum_register_static (
+				g_intern_static_string ("LsmDomNodeType"),
+				values);
+	}
+	return the_type;
+}
+
+
+/* Generated data ends here */
+
diff --git a/src/lsmdomenumtypes.h b/src/lsmdomenumtypes.h
new file mode 100644
index 0000000..1575ad3
--- /dev/null
+++ b/src/lsmdomenumtypes.h
@@ -0,0 +1,26 @@
+
+/* Generated data (by glib-mkenums) */
+
+#ifndef LSM_DOM_ENUM_TYPES_H
+#define LSM_DOM_ENUM_TYPES_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* Enumerations from "lsmdebug.h" */
+
+#define LSM_TYPE_DEBUG_LEVEL	(lsm_debug_level_get_type())
+GType lsm_debug_level_get_type	(void) G_GNUC_CONST;
+
+/* Enumerations from "lsmdomnode.h" */
+
+#define LSM_TYPE_DOM_NODE_TYPE	(lsm_dom_node_type_get_type())
+GType lsm_dom_node_type_get_type	(void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* LSM_DOM_ENUM_TYPES_H */
+
+/* Generated data ends here */
+
diff --git a/src/lsmdomimplementation.c b/src/lsmdomimplementation.c
new file mode 100644
index 0000000..66b2566
--- /dev/null
+++ b/src/lsmdomimplementation.c
@@ -0,0 +1,73 @@
+/* Lasem
+ *
+ * Copyright  2007-2009 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#include <lsmdomimplementation.h>
+#include <lsmmathmldocument.h>
+#include <lsmsvgdocument.h>
+#include <lsmdebug.h>
+#include <string.h>
+
+static GHashTable *document_types = NULL;
+
+void
+lsm_dom_implementation_add_create_function (const char *qualified_name,
+					    LsmDomDocumentCreateFunction create_function)
+{
+	if (document_types == NULL)
+		document_types = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+	g_hash_table_insert (document_types, g_strdup (qualified_name), create_function);
+}
+
+LsmDomDocument *
+lsm_dom_implementation_create_document (const char *namespace_uri,
+					const char *qualified_name)
+{
+	LsmDomDocumentCreateFunction create_function;
+
+	g_return_val_if_fail (qualified_name != NULL, NULL);
+
+	if (document_types == NULL) {
+		lsm_dom_implementation_add_create_function ("math", lsm_mathml_document_new);
+		lsm_dom_implementation_add_create_function ("svg", lsm_svg_document_new);
+	}
+
+	create_function = g_hash_table_lookup (document_types, qualified_name);
+	if (create_function == NULL) {
+		lsm_debug_dom ("[LsmDomImplementation::create_document] Unknow document type (%s)",
+			   qualified_name);
+		return NULL;
+	}
+
+	return create_function ();
+}
+
+void
+lsm_dom_implementation_cleanup (void)
+{
+	if (document_types == NULL)
+		return;
+
+	g_hash_table_unref (document_types);
+	document_types = NULL;
+}
diff --git a/src/lsmdomimplementation.h b/src/lsmdomimplementation.h
new file mode 100644
index 0000000..61b6b03
--- /dev/null
+++ b/src/lsmdomimplementation.h
@@ -0,0 +1,43 @@
+/* Lasem
+ *
+ * Copyright  2007-2009 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_DOM_IMPLEMENTATION_H
+#define LSM_DOM_IMPLEMENTATION_H
+
+#include <lsmdomtypes.h>
+#include <lsmdomdocument.h>
+
+G_BEGIN_DECLS
+
+typedef LsmDomDocument * (*LsmDomDocumentCreateFunction) (void);
+
+LsmDomDocument *	lsm_dom_implementation_create_document 			(const char *namespace_uri,
+										 const char *qualified_name);
+void			lsm_dom_implementation_add_document_create_function	(const char *qualified_name,
+										 LsmDomDocumentCreateFunction create_function);
+
+void			lsm_dom_implementation_cleanup 				(void);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmdomnamednodemap.c b/src/lsmdomnamednodemap.c
new file mode 100644
index 0000000..fd7fd85
--- /dev/null
+++ b/src/lsmdomnamednodemap.c
@@ -0,0 +1,81 @@
+/* Lasem
+ *
+ * Copyright  2010 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#include <lsmdomnamednodemap.h>
+#include <lsmdomnode.h>
+
+/* LsmDomNamedNodeMap implementation */
+
+LsmDomNode *
+lsm_dom_named_node_map_get_named_item (LsmDomNamedNodeMap *map, const char *name)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NAMED_NODE_MAP (map), NULL);
+
+	return LSM_DOM_NAMED_NODE_MAP_GET_CLASS (map)->get (map, name);
+}
+
+LsmDomNode *
+lsm_dom_named_node_map_set_named_item (LsmDomNamedNodeMap *map, LsmDomNode *node)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NAMED_NODE_MAP (map), NULL);
+
+	return LSM_DOM_NAMED_NODE_MAP_GET_CLASS (map)->set (map, node);
+}
+
+LsmDomNode *
+lsm_dom_named_node_map_remove_named_item (LsmDomNamedNodeMap *map, const char *name)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NAMED_NODE_MAP (map), NULL);
+
+	return LSM_DOM_NAMED_NODE_MAP_GET_CLASS (map)->remove (map, name);
+}
+
+LsmDomNode *
+lsm_dom_named_node_map_get_item (LsmDomNamedNodeMap *map, unsigned int index)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NAMED_NODE_MAP (map), NULL);
+
+	return LSM_DOM_NAMED_NODE_MAP_GET_CLASS (map)->get_item (map, index);
+}
+
+unsigned int
+lsm_dom_named_node_map_get_length (LsmDomNamedNodeMap *map)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NAMED_NODE_MAP (map), 0);
+
+	return LSM_DOM_NAMED_NODE_MAP_GET_CLASS (map)->get_length (map);
+}
+
+static void
+lsm_dom_named_node_map_init (LsmDomNamedNodeMap *map)
+{
+}
+
+/* LsmDomNamedNodeMap class */
+
+static void
+lsm_dom_named_node_map_class_init (LsmDomNamedNodeMapClass *klass)
+{
+}
+
+G_DEFINE_ABSTRACT_TYPE (LsmDomNamedNodeMap, lsm_dom_named_node_map, G_TYPE_OBJECT)
diff --git a/src/lsmdomnamednodemap.h b/src/lsmdomnamednodemap.h
new file mode 100644
index 0000000..2821089
--- /dev/null
+++ b/src/lsmdomnamednodemap.h
@@ -0,0 +1,64 @@
+/* Lasem
+ *
+ * Copyright  2010 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_DOM_NAMED_NODE_MAP_H
+#define LSM_DOM_NAMED_NODE_MAP_H
+
+#include <lsmdomtypes.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_DOM_NAMED_NODE_MAP             (lsm_dom_named_node_map_get_type ())
+#define LSM_DOM_NAMED_NODE_MAP(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_DOM_NAMED_NODE_MAP, LsmDomNamedNodeMap))
+#define LSM_DOM_NAMED_NODE_MAP_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_DOM_NAMED_NODE_MAP, LsmDomNamedNodeMapClass))
+#define LSM_IS_DOM_NAMED_NODE_MAP(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_DOM_NAMED_NODE_MAP))
+#define LSM_IS_DOM_NAMED_NODE_MAP_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_DOM_NAMED_NODE_MAP))
+#define LSM_DOM_NAMED_NODE_MAP_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_DOM_NAMED_NODE_MAP, LsmDomNamedNodeMapClass))
+
+typedef struct _LsmDomNamedNodeMapClass LsmDomNamedNodeMapClass;
+
+struct _LsmDomNamedNodeMap {
+	GObject	object;
+};
+
+struct _LsmDomNamedNodeMapClass {
+	GObjectClass parent_class;
+
+	LsmDomNode *	(*get) 			(LsmDomNamedNodeMap *map, const char *name);
+	LsmDomNode *	(*set) 			(LsmDomNamedNodeMap *map, LsmDomNode *node);
+	LsmDomNode *	(*remove) 		(LsmDomNamedNodeMap *map, const char *name);
+	LsmDomNode *	(*get_item) 		(LsmDomNamedNodeMap *map, unsigned int index);
+	unsigned int	(*get_length)		(LsmDomNamedNodeMap *map);
+};
+
+GType lsm_dom_named_node_map_get_type (void);
+
+LsmDomNode *		lsm_dom_named_node_map_get_named_item 		(LsmDomNamedNodeMap *map, const char *name);
+LsmDomNode *		lsm_dom_named_node_map_set_named_item 		(LsmDomNamedNodeMap *map, LsmDomNode *item);
+LsmDomNode *		lsm_dom_named_node_map_remove_named_item	(LsmDomNamedNodeMap *map, const char *name);
+LsmDomNode *		lsm_dom_named_node_map_get_item 		(LsmDomNamedNodeMap *map, unsigned int index);
+unsigned int		lsm_dom_named_node_map_get_length		(LsmDomNamedNodeMap *map);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmdomnode.c b/src/lsmdomnode.c
new file mode 100644
index 0000000..933aa57
--- /dev/null
+++ b/src/lsmdomnode.c
@@ -0,0 +1,672 @@
+/* Lasem
+ *
+ * Copyright  2007-2010 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+/**
+ * SECTION:lsmdomnode
+ * @short_description: Base class for DOM nodes
+ */
+
+#include <lsmdomnode.h>
+#include <lsmdomnodelist.h>
+#include <lsmdomdocument.h>
+#include <lsmdebug.h>
+#include <glib/gprintf.h>
+#include <stdio.h>
+
+/* LsmDomNodeChildList */
+
+
+#define LSM_TYPE_DOM_NODE_CHILD_LIST             (lsm_dom_node_child_list_get_type ())
+#define LSM_DOM_NODE_CHILD_LIST(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_DOM_NODE_CHILD_LIST, LsmDomNodeChildList))
+#define LSM_DOM_NODE_CHILD_LIST_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_DOM_NODE_CHILD_LIST, LsmDomNodeChildListClass))
+#define LSM_IS_DOM_NODE_CHILD_LIST(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_DOM_NODE_CHILD_LIST))
+#define LSM_IS_DOM_NODE_CHILD_LIST_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_DOM_NODE_CHILD_LIST))
+#define LSM_DOM_NODE_CHILD_LIST_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_DOM_NODE_CHILD_LIST, LsmDomNodeChildListClass))
+
+typedef struct _LsmDomNodeChildListClass LsmDomNodeChildListClass;
+
+typedef struct {
+	LsmDomNodeList base;
+
+	LsmDomNode *parent_node;
+} LsmDomNodeChildList;
+
+struct _LsmDomNodeChildListClass {
+	LsmDomNodeListClass parent_class;
+};
+
+GType lsm_dom_node_child_list_get_type (void);
+
+static GObjectClass *child_list_parent_class = NULL;
+
+static void
+lsm_dom_node_child_list_weak_notify_cb (void *user_data, GObject *object)
+{
+	LsmDomNodeChildList *list = user_data;
+
+	list->parent_node = NULL;
+}
+
+static LsmDomNode *
+lsm_dom_node_child_list_get_item (LsmDomNodeList *list, unsigned int index)
+{
+	LsmDomNodeChildList *child_list = LSM_DOM_NODE_CHILD_LIST (list);
+	LsmDomNode *iter;
+	unsigned int i = 0;
+
+	if (child_list->parent_node == NULL)
+		return NULL;
+
+	for (iter = child_list->parent_node->first_child; iter != NULL; iter = iter->next_sibling) {
+		if (i == index)
+			return iter;
+		i++;
+	}
+
+	return NULL;
+}
+
+static unsigned int
+lsm_dom_node_child_list_get_length (LsmDomNodeList *list)
+{
+	LsmDomNodeChildList *child_list = LSM_DOM_NODE_CHILD_LIST (list);
+	LsmDomNode *iter;
+	unsigned int length = 0;
+
+	if (child_list->parent_node == NULL)
+		return 0;
+
+	for (iter = child_list->parent_node->first_child; iter != NULL; iter = iter->next_sibling)
+		length++;
+
+	return length;
+}
+
+LsmDomNodeList *
+lsm_dom_node_child_list_new (LsmDomNode *parent_node)
+{
+	LsmDomNodeChildList *list;
+
+	g_return_val_if_fail (LSM_IS_DOM_NODE (parent_node), NULL);
+
+	list = g_object_new (LSM_TYPE_DOM_NODE_CHILD_LIST, NULL);
+	list->parent_node = parent_node;
+
+	g_object_weak_ref (G_OBJECT (parent_node), lsm_dom_node_child_list_weak_notify_cb, list);
+
+	return LSM_DOM_NODE_LIST (list);
+}
+
+static void
+lsm_dom_node_child_list_init (LsmDomNodeChildList *list)
+{
+}
+
+static void
+lsm_dom_node_child_list_finalize (GObject *object)
+{
+	LsmDomNodeChildList *list = LSM_DOM_NODE_CHILD_LIST (object);
+
+	if (list->parent_node != NULL) {
+		g_object_weak_unref (G_OBJECT (list->parent_node), lsm_dom_node_child_list_weak_notify_cb, list);
+		list->parent_node = NULL;
+	}
+
+	child_list_parent_class->finalize (object);
+}
+
+static void
+lsm_dom_node_child_list_class_init (LsmDomNodeChildListClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	LsmDomNodeListClass *node_list_class = LSM_DOM_NODE_LIST_CLASS (klass);
+
+	child_list_parent_class = g_type_class_peek_parent (klass);
+
+	object_class->finalize = lsm_dom_node_child_list_finalize;
+
+	node_list_class->get_item = lsm_dom_node_child_list_get_item;
+	node_list_class->get_length = lsm_dom_node_child_list_get_length;
+}
+
+G_DEFINE_TYPE (LsmDomNodeChildList, lsm_dom_node_child_list, LSM_TYPE_DOM_NODE_LIST)
+
+static GObjectClass *parent_class = NULL;
+
+/* LsmDomNode implementation */
+
+
+/**
+ * lsm_dom_node_get_node_name:
+ * @self: a #LsmDomNode
+ * Return value: the node name.
+ *
+ * Gets the node name.
+ */
+
+const char*
+lsm_dom_node_get_node_name (LsmDomNode* self)
+{
+	LsmDomNodeClass *node_class = LSM_DOM_NODE_GET_CLASS (self);
+
+	g_return_val_if_fail (node_class != NULL, NULL);
+
+	if (node_class->get_node_name)
+		return node_class->get_node_name (self);
+
+	return NULL;
+}
+
+/**
+ * lsm_dom_node_get_node_value:
+ * @self: a #LsmDomNode
+ * Return value: the node value.
+ *
+ * Gets the node value.
+ */
+
+const char*
+lsm_dom_node_get_node_value (LsmDomNode* self)
+{
+	LsmDomNodeClass *node_class = LSM_DOM_NODE_GET_CLASS (self);
+
+	g_return_val_if_fail (node_class != NULL, NULL);
+
+	if (node_class->get_node_value)
+		return node_class->get_node_value (self);
+
+	return NULL;
+}
+
+void
+lsm_dom_node_set_node_value (LsmDomNode* self, const char* new_value)
+{
+	LsmDomNodeClass *node_class = LSM_DOM_NODE_GET_CLASS (self);
+
+	g_return_if_fail (node_class != NULL);
+	g_return_if_fail (new_value != NULL);
+
+	if (node_class->set_node_value)
+		node_class->set_node_value (self, new_value);
+}
+
+LsmDomNodeType lsm_dom_node_get_node_type (LsmDomNode* self)
+{
+	LsmDomNodeClass *node_class = LSM_DOM_NODE_GET_CLASS (self);
+
+	g_return_val_if_fail (node_class != NULL, 0);
+
+	if (node_class->get_node_type)
+		return node_class->get_node_type (self);
+
+	return 0;
+}
+
+LsmDomNode*
+lsm_dom_node_get_parent_node (LsmDomNode* self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NODE (self), NULL);
+
+	return self->parent_node;
+}
+
+LsmDomNodeList*
+lsm_dom_node_get_child_nodes (LsmDomNode* self)
+{
+	LsmDomNodeList *list;
+
+	g_return_val_if_fail (LSM_IS_DOM_NODE (self), NULL);
+
+	list = g_object_get_data (G_OBJECT (self), "child-nodes");
+
+	if (list == NULL) {
+		list = lsm_dom_node_child_list_new (self);
+		g_object_set_data_full (G_OBJECT (self), "child-nodes", list, g_object_unref);
+	}
+
+	return list;
+}
+
+LsmDomNode*
+lsm_dom_node_get_first_child (LsmDomNode* self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NODE (self), NULL);
+
+	return self->first_child;
+}
+
+LsmDomNode*
+lsm_dom_node_get_last_child (LsmDomNode* self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NODE (self), NULL);
+
+	return self->last_child;
+}
+
+LsmDomNode*
+lsm_dom_node_get_previous_sibling (LsmDomNode* self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NODE (self), NULL);
+
+	return self->previous_sibling;
+}
+
+LsmDomNode*
+lsm_dom_node_get_next_sibling (LsmDomNode* self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NODE (self), NULL);
+
+	return self->next_sibling;
+}
+
+/*LsmDomNamedNodeMap**/
+/*lsm_dom_node_get_attributes (LsmDomNode* self)*/
+/*{*/
+/*        return LSM_DOM_NODE_GET_CLASS (self)->get_attributes (self);*/
+/*}*/
+
+LsmDomDocument*
+lsm_dom_node_get_owner_document (LsmDomNode* self)
+{
+	LsmDomNode *parent;
+
+	g_return_val_if_fail (LSM_IS_DOM_NODE (self), NULL);
+
+	for (parent = self;
+	     parent != NULL &&
+	     !LSM_IS_DOM_DOCUMENT (parent);
+	     parent = parent->parent_node);
+
+	return LSM_DOM_DOCUMENT (parent);
+}
+
+/**
+ * lsm_dom_node_insert_before:
+ * @self: a #LsmDomNode
+ * @new_child: (transfer full): node to insert
+ * @ref_child: (transfer none): reference node, i.e., the node before which the new node must be inserted.
+ *
+ * Inserts the node @new_child before the existing child node @ref_child. If
+ * @ref_child is null, insert @new_child at the end of the list of children.
+ * If the @new_child is already in the tree, it is first removed.
+ *
+ * Returns: (transfer none): the inserted node.
+ */
+
+/* TODO:
+ * If @new_child is a #LsmDocumentFragment object, all of its children are inserted,
+ * in the same order, before @ref_child. 
+ * Check if new_child is an ancestor of self.
+ */
+
+LsmDomNode*
+lsm_dom_node_insert_before (LsmDomNode* self, LsmDomNode* new_child, LsmDomNode* ref_child)
+{
+	LsmDomNodeClass *node_class;
+
+	if (ref_child == NULL)
+		lsm_dom_node_append_child (self, new_child);
+
+	g_return_val_if_fail (LSM_IS_DOM_NODE (new_child), NULL);
+
+	if (new_child->parent_node != NULL)
+		lsm_dom_node_remove_child (self, new_child);
+
+	if (!LSM_IS_DOM_NODE (self)) {
+		g_critical ("%s: self is not a LsmDomNode", G_STRFUNC);
+		g_object_unref (new_child);
+		return NULL;
+	}
+
+	if (!LSM_IS_DOM_NODE (ref_child)) {
+		g_critical ("%s: ref_child is not a LsmDomNode", G_STRFUNC);
+		g_object_unref (new_child);
+		return NULL;
+	}
+
+	if (ref_child->parent_node != self) {
+		lsm_debug_dom ("[LsmDomNode::insert_before] Ref child '%s' doesn't belong to '%s'",
+			   lsm_dom_node_get_node_name (ref_child),
+			   lsm_dom_node_get_node_name (self));
+		g_object_unref (new_child);
+		return NULL;
+	}
+
+	if (!LSM_DOM_NODE_GET_CLASS (self)->can_append_child (self, new_child)) {
+		lsm_debug_dom ("[LsmDomNode::insert_before] Can't append '%s' to '%s'",
+			   lsm_dom_node_get_node_name (new_child),
+			   lsm_dom_node_get_node_name (self));
+		g_object_unref (new_child);
+		return NULL;
+	}
+
+	new_child->parent_node = self;
+	new_child->next_sibling = ref_child;
+	new_child->previous_sibling = ref_child->previous_sibling;
+
+	if (ref_child->previous_sibling == NULL)
+		self->first_child = new_child;
+	else
+		ref_child->previous_sibling->next_sibling = new_child;
+
+	ref_child->previous_sibling = new_child;
+
+	node_class = LSM_DOM_NODE_GET_CLASS (self);
+
+	if (node_class->post_new_child)
+		node_class->post_new_child (self, new_child);
+
+	lsm_dom_node_changed (self);
+
+	return new_child;
+}
+
+/**
+ * lsm_dom_node_replace_child:
+ * @self: a #LsmDomNode
+ * @new_child: (transfer full): a replacement node
+ * @old_child: (transfer none): node to replace
+ *
+ * Replaces the child node @old_child with @new_child in the list of children,
+ * and returns the @old_child node.
+ * If the @new_child is already in the tree, it is first removed.
+ *
+ * Returns: (transfer full): the replaced node.
+ */
+
+/* TODO:
+ * Check if new_child is an ancestor of self.
+ */
+
+LsmDomNode*
+lsm_dom_node_replace_child (LsmDomNode* self, LsmDomNode* new_child, LsmDomNode* old_child)
+{
+	LsmDomNode *next_sibling;
+	LsmDomNode *node;
+
+	if (new_child == NULL)
+		return lsm_dom_node_remove_child (self, old_child);
+
+	if (!LSM_IS_DOM_NODE (new_child)) {
+		g_critical ("%s: new_child is not a LsmDomNode", G_STRFUNC);
+		if (LSM_IS_DOM_NODE (old_child))
+			g_object_unref (old_child);
+		return NULL;
+	}
+
+	if (new_child->parent_node != NULL)
+		lsm_dom_node_remove_child (self, new_child);
+
+	if (old_child == NULL) {
+		lsm_debug_dom ("[LsmDomNode::replace_child] old_child == NULL)");
+		g_object_unref (new_child);
+		return NULL;
+	}
+
+	if (!LSM_IS_DOM_NODE (old_child)) {
+		g_critical ("%s: old_child is not a LsmDomNode", G_STRFUNC);
+		g_object_unref (new_child);
+		return NULL;
+	}
+
+	if (!LSM_IS_DOM_NODE (self)) {
+		g_critical ("%s: self is not a LsmDomNode", G_STRFUNC);
+		g_object_unref (new_child);
+		g_object_unref (old_child);
+		return NULL;
+	}
+
+	if (old_child->parent_node != self) {
+		g_object_unref (new_child);
+		g_object_unref (old_child);
+		return NULL;
+	}
+
+	next_sibling = old_child->next_sibling;
+
+	node = lsm_dom_node_remove_child (self, old_child);
+	if (node != old_child) {
+		g_object_unref (new_child);
+		g_object_unref (old_child);
+		return NULL;
+	}
+
+	if (next_sibling == NULL)
+		lsm_dom_node_append_child (self, new_child);
+	else
+		lsm_dom_node_insert_before (self, new_child, next_sibling);
+
+	return old_child;
+}
+
+/**
+ * lsm_dom_node_remove_child:
+ * @self: a #LsmDomNode
+ * @old_child: (transfer none): node to remove.
+ *
+ * Removes the child node indicated by @old_child from the list of children, and returns it.
+ *
+ * Returns: (transfer full): the removed node.
+ */
+
+LsmDomNode*
+lsm_dom_node_remove_child (LsmDomNode* self, LsmDomNode* old_child)
+{
+	LsmDomNode *node;
+	LsmDomNodeClass *node_class;
+
+	g_return_val_if_fail (LSM_IS_DOM_NODE (self), NULL);
+
+	if (old_child == NULL)
+		return NULL;
+
+	g_return_val_if_fail (LSM_IS_DOM_NODE (old_child), NULL);
+
+	for (node = self->first_child;
+	     node != NULL && node != old_child;
+	     node = node->next_sibling);
+
+	if (node == NULL)
+		return NULL;
+
+	node_class = LSM_DOM_NODE_GET_CLASS (self);
+
+	if (node_class->pre_remove_child)
+		node_class->pre_remove_child (self, old_child);
+
+	if (self->first_child == old_child)
+		self->first_child = old_child->next_sibling;
+	if (self->last_child == old_child)
+		self->last_child = old_child->previous_sibling;
+
+	if (old_child->next_sibling != NULL)
+		old_child->next_sibling->previous_sibling = old_child->previous_sibling;
+	if (old_child->previous_sibling != NULL)
+		old_child->previous_sibling->next_sibling = old_child->next_sibling;
+
+	old_child->parent_node = NULL;
+	old_child->next_sibling = NULL;
+	old_child->previous_sibling = NULL;
+
+	lsm_dom_node_changed (self);
+
+	return old_child;
+}
+
+/**
+ * lsm_dom_node_append_child:
+ * @self: a #LsmDomNode
+ * @new_child: (transfer full): node to append
+ *
+ * Adds the node @new_child to the end of the list of children of this node.
+ * If the @new_child is already in the tree, it is first removed.
+ *
+ * Returns: (transfer none): the added node.
+ */
+
+LsmDomNode *
+lsm_dom_node_append_child (LsmDomNode* self, LsmDomNode* new_child)
+{
+	LsmDomNodeClass *node_class;
+
+	if (new_child == NULL)
+		return NULL;
+
+	g_return_val_if_fail (LSM_IS_DOM_NODE (new_child), NULL);
+
+	if (!LSM_IS_DOM_NODE (self)) {
+		g_critical ("%s: self is not a LsmDomNode", G_STRFUNC);
+		g_object_unref (new_child);
+		return NULL;
+	}
+
+	if (new_child->parent_node != NULL)
+		lsm_dom_node_remove_child (self, new_child);
+
+	if (!LSM_DOM_NODE_GET_CLASS (self)->can_append_child (self, new_child)) {
+		lsm_debug_dom ("[LsmDomNode::append_child] Can't append '%s' to '%s'",
+			   lsm_dom_node_get_node_name (new_child),
+			   lsm_dom_node_get_node_name (self));
+		g_object_unref (new_child);
+		return NULL;
+	}
+
+	if (self->first_child == NULL)
+		self->first_child = new_child;
+	if (self->last_child != NULL)
+		self->last_child->next_sibling = new_child;
+
+	new_child->parent_node = self;
+	new_child->next_sibling = NULL;
+	new_child->previous_sibling = self->last_child;
+	self->last_child = new_child;
+
+	node_class = LSM_DOM_NODE_GET_CLASS (self);
+
+	if (node_class->post_new_child)
+		node_class->post_new_child (self, new_child);
+
+	lsm_dom_node_changed (self);
+
+	return new_child;
+}
+
+static gboolean
+lsm_dom_node_can_append_child_default (LsmDomNode *self, LsmDomNode* new_child)
+{
+	return FALSE;
+}
+
+void
+lsm_dom_node_changed (LsmDomNode *self)
+{
+	LsmDomNode *parent_node;
+	LsmDomNode *child_node;
+	LsmDomNodeClass *node_class;
+
+	g_return_if_fail (LSM_IS_DOM_NODE (self));
+
+	node_class = LSM_DOM_NODE_GET_CLASS (self);
+
+	if (node_class->changed)
+		node_class->changed (self);
+
+	child_node = self;
+	for (parent_node = self->parent_node;
+	       parent_node != NULL;
+	       parent_node = parent_node->parent_node) {
+		node_class = LSM_DOM_NODE_GET_CLASS (parent_node);
+		if (node_class->child_changed == NULL ||
+		    !node_class->child_changed (parent_node, child_node))
+			break;
+		child_node = parent_node;
+	}
+}
+
+gboolean
+lsm_dom_node_has_child_nodes (LsmDomNode* self)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NODE (self), FALSE);
+
+	return self->first_child != NULL;
+}
+
+static void
+lsm_dom_node_write_to_stream_default (LsmDomNode *self, GOutputStream *stream, GError **error)
+{
+	LsmDomNode *child;
+
+	for (child = self->first_child; child != NULL; child = child->next_sibling)
+		lsm_dom_node_write_to_stream (child, stream, error);
+}
+
+void
+lsm_dom_node_write_to_stream (LsmDomNode *self, GOutputStream *stream, GError **error)
+{
+	LsmDomNodeClass *node_class;
+
+	g_return_if_fail (LSM_IS_DOM_NODE (self));
+	g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
+
+	node_class = LSM_DOM_NODE_GET_CLASS (self);
+	if (node_class->write_to_stream != NULL)
+		node_class->write_to_stream (self, stream, error);
+}
+
+static void
+lsm_dom_node_init (LsmDomNode *node)
+{
+}
+
+static void
+lsm_dom_node_finalize (GObject *object)
+{
+	LsmDomNode *node = LSM_DOM_NODE (object);
+	LsmDomNode *child, *next_child;
+
+	child = node->first_child;
+	while (child != NULL) {
+		next_child = child->next_sibling;
+		g_object_unref (child);
+		child = next_child;
+	}
+
+	parent_class->finalize (object);
+}
+
+/* LsmDomNode class */
+
+static void
+lsm_dom_node_class_init (LsmDomNodeClass *node_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (node_class);
+
+	parent_class = g_type_class_peek_parent (node_class);
+
+	object_class->finalize = lsm_dom_node_finalize;
+
+	node_class->can_append_child = lsm_dom_node_can_append_child_default;
+	node_class->write_to_stream = lsm_dom_node_write_to_stream_default;
+}
+
+G_DEFINE_ABSTRACT_TYPE (LsmDomNode, lsm_dom_node, G_TYPE_OBJECT)
diff --git a/src/lsmdomnode.h b/src/lsmdomnode.h
new file mode 100644
index 0000000..de1458c
--- /dev/null
+++ b/src/lsmdomnode.h
@@ -0,0 +1,120 @@
+/* Lasem
+ *
+ * Copyright  2007-2008 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_DOM_NODE_H
+#define LSM_DOM_NODE_H
+
+#include <lsmdomtypes.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+typedef enum  {
+	LSM_DOM_NODE_TYPE_ELEMENT_NODE = 1,
+	LSM_DOM_NODE_TYPE_ATTRIBUTE_NODE,
+	LSM_DOM_NODE_TYPE_TEXT_NODE,
+	LSM_DOM_NODE_TYPE_CDATA_SECTION_NODE,
+	LSM_DOM_NODE_TYPE_ENTITY_REFERENCE_NODE,
+	LSM_DOM_NODE_TYPE_ENTITY_NODE,
+	LSM_DOM_NODE_TYPE_PROCESSING_INSTRUCTION_NODE,
+	LSM_DOM_NODE_TYPE_COMMENT_NODE,
+	LSM_DOM_NODE_TYPE_DOCUMENT_NODE,
+	LSM_DOM_NODE_TYPE_DOCUMENT_TYPE_NODE,
+	LSM_DOM_NODE_TYPE_DOCUMENT_FRAGMENT_NODE,
+	LSM_DOM_NODE_TYPE_NOTATION_NODE
+} LsmDomNodeType;
+
+#define LSM_TYPE_DOM_NODE             (lsm_dom_node_get_type ())
+#define LSM_DOM_NODE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_DOM_NODE, LsmDomNode))
+#define LSM_DOM_NODE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_DOM_NODE, LsmDomNodeClass))
+#define LSM_IS_DOM_NODE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_DOM_NODE))
+#define LSM_IS_DOM_NODE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_DOM_NODE))
+#define LSM_DOM_NODE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_DOM_NODE, LsmDomNodeClass))
+
+typedef struct _LsmDomNodeClass LsmDomNodeClass;
+
+struct _LsmDomNode {
+	GObject	object;
+
+	LsmDomNode	*next_sibling;
+	LsmDomNode	*previous_sibling;
+	LsmDomNode	*parent_node;
+	LsmDomNode	*first_child;
+	LsmDomNode	*last_child;
+};
+
+struct _LsmDomNodeClass {
+	GObjectClass parent_class;
+
+	/* DOM node virtuals */
+
+	const char* 		(*get_node_name) 	(LsmDomNode* self);
+	const char* 		(*get_node_value) 	(LsmDomNode* self);
+	void 			(*set_node_value) 	(LsmDomNode* self, const char* new_value);
+	LsmDomNodeType 		(*get_node_type) 	(LsmDomNode* self);
+
+	/* Validation virtuals */
+
+	gboolean		(*can_append_child) 	(LsmDomNode *self, LsmDomNode *new_child);
+
+	/* Implementation virtuals */
+
+	void			(*post_new_child) 	(LsmDomNode *parent, LsmDomNode *child);
+	void			(*pre_remove_child) 	(LsmDomNode *parent, LsmDomNode *child);
+	void			(*changed)		(LsmDomNode *self);
+	gboolean		(*child_changed)	(LsmDomNode *self, LsmDomNode *child);
+
+	void			(*write_to_stream)	(LsmDomNode *self, GOutputStream *stream, GError **error);
+};
+
+GType lsm_dom_node_get_type (void);
+
+const char * 		lsm_dom_node_get_node_name 		(LsmDomNode* self);
+const char * 		lsm_dom_node_get_node_value 		(LsmDomNode* self);
+void 			lsm_dom_node_set_node_value 		(LsmDomNode* self, const char* new_value);
+LsmDomNodeType 		lsm_dom_node_get_node_type 		(LsmDomNode* self);
+LsmDomNode * 		lsm_dom_node_get_parent_node 		(LsmDomNode* self);
+LsmDomNodeList *	lsm_dom_node_get_child_nodes 		(LsmDomNode* self);
+LsmDomNode * 		lsm_dom_node_get_first_child 		(LsmDomNode* self);
+LsmDomNode * 		lsm_dom_node_get_last_child 		(LsmDomNode* self);
+LsmDomNode * 		lsm_dom_node_get_previous_sibling 	(LsmDomNode* self);
+LsmDomNode * 		lsm_dom_node_get_next_sibling 		(LsmDomNode* self);
+#if 0
+LsmDomNamedNodeMap * 	lsm_dom_node_get_attributes 		(LsmDomNode* self);
+#endif
+LsmDomNode * 		lsm_dom_node_insert_before		(LsmDomNode* self, LsmDomNode* new_child, LsmDomNode* ref_child);
+LsmDomNode * 		lsm_dom_node_replace_child 		(LsmDomNode* self, LsmDomNode* new_child, LsmDomNode* old_child);
+LsmDomNode * 		lsm_dom_node_append_child 		(LsmDomNode* self, LsmDomNode* new_child);
+LsmDomNode * 		lsm_dom_node_remove_child 		(LsmDomNode* self, LsmDomNode* old_child);
+gboolean 		lsm_dom_node_has_child_nodes 		(LsmDomNode* self);
+
+void 			lsm_dom_node_changed 			(LsmDomNode *self);
+
+LsmDomDocument *	lsm_dom_node_get_owner_document 	(LsmDomNode* self);
+
+void			lsm_dom_node_write_to_stream		(LsmDomNode *self, GOutputStream *stream,
+								 GError **error);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmdomnodelist.c b/src/lsmdomnodelist.c
new file mode 100644
index 0000000..e896c91
--- /dev/null
+++ b/src/lsmdomnodelist.c
@@ -0,0 +1,57 @@
+/* Lasem
+ *
+ * Copyright  2010 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#include <lsmdomnodelist.h>
+#include <lsmdomnode.h>
+
+/* LsmDomNodeList implementation */
+
+LsmDomNode *
+lsm_dom_node_list_get_item (LsmDomNodeList *list, unsigned int index)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NODE_LIST (list), NULL);
+
+	return LSM_DOM_NODE_LIST_GET_CLASS (list)->get_item (list, index);
+}
+
+unsigned int
+lsm_dom_node_list_get_length (LsmDomNodeList *list)
+{
+	g_return_val_if_fail (LSM_IS_DOM_NODE_LIST (list), 0);
+
+	return LSM_DOM_NODE_LIST_GET_CLASS (list)->get_length (list);
+}
+
+static void
+lsm_dom_node_list_init (LsmDomNodeList *list)
+{
+}
+
+/* LsmDomNodeList class */
+
+static void
+lsm_dom_node_list_class_init (LsmDomNodeListClass *klass)
+{
+}
+
+G_DEFINE_ABSTRACT_TYPE (LsmDomNodeList, lsm_dom_node_list, G_TYPE_OBJECT)
diff --git a/src/lsmdomnodelist.h b/src/lsmdomnodelist.h
new file mode 100644
index 0000000..df52bed
--- /dev/null
+++ b/src/lsmdomnodelist.h
@@ -0,0 +1,58 @@
+/* Lasem
+ *
+ * Copyright  2010 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_DOM_NODE_LIST_H
+#define LSM_DOM_NODE_LIST_H
+
+#include <lsmdomtypes.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_DOM_NODE_LIST             (lsm_dom_node_list_get_type ())
+#define LSM_DOM_NODE_LIST(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_DOM_NODE_LIST, LsmDomNodeList))
+#define LSM_DOM_NODE_LIST_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_DOM_NODE_LIST, LsmDomNodeListClass))
+#define LSM_IS_DOM_NODE_LIST(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_DOM_NODE_LIST))
+#define LSM_IS_DOM_NODE_LIST_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_DOM_NODE_LIST))
+#define LSM_DOM_NODE_LIST_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_DOM_NODE_LIST, LsmDomNodeListClass))
+
+typedef struct _LsmDomNodeListClass LsmDomNodeListClass;
+
+struct _LsmDomNodeList {
+	GObject	object;
+};
+
+struct _LsmDomNodeListClass {
+	GObjectClass parent_class;
+
+	LsmDomNode *	(*get_item) 		(LsmDomNodeList *list, unsigned int index);
+	unsigned int	(*get_length)		(LsmDomNodeList *list);
+};
+
+GType lsm_dom_node_list_get_type (void);
+
+LsmDomNode *		lsm_dom_node_list_get_item 		(LsmDomNodeList *list, unsigned int index);
+unsigned int		lsm_dom_node_list_get_length		(LsmDomNodeList *list);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmdomparser.c b/src/lsmdomparser.c
new file mode 100644
index 0000000..8f42734
--- /dev/null
+++ b/src/lsmdomparser.c
@@ -0,0 +1,423 @@
+/* Lasem
+ *
+ * Copyright  2007-2009 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#include <lsmdebug.h>
+#include <lsmdomimplementation.h>
+#include <lsmdomnode.h>
+#include <lsmmathmlpresentationtoken.h>
+#include <lsmmathmlentitydictionary.h>
+#include <lsmsvgtextelement.h>
+#include <lsmstr.h>
+#include <libxml/parser.h>
+#include <gio/gio.h>
+#include <string.h>
+#include <../itex2mml/itex2MML.h>
+
+typedef enum {
+	STATE
+} LsmDomSaxParserStateEnum;
+
+typedef struct {
+	LsmDomSaxParserStateEnum state;
+
+	LsmDomDocument *document;
+	LsmDomNode *current_node;
+
+	gboolean is_error;
+
+	int error_depth;
+
+	GHashTable *entities;
+} LsmDomSaxParserState;
+
+void
+_free_entity (void *data)
+{
+	xmlEntity *entity = data;
+
+	xmlFree ((xmlChar *) entity->name);
+	xmlFree ((xmlChar *) entity->ExternalID);
+	xmlFree ((xmlChar *) entity->SystemID);
+	xmlFree (entity->content);
+	xmlFree (entity->orig);
+	g_free (entity);
+}
+
+static void
+lsm_dom_parser_start_document (void *user_data)
+{
+	LsmDomSaxParserState *state = user_data;
+
+	state->state = STATE;
+	state->document = NULL;
+	state->is_error = FALSE;
+	state->error_depth = 0;
+	state->entities = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, _free_entity);
+}
+
+static void
+lsm_dom_parser_end_document (void *user_data)
+{
+	LsmDomSaxParserState *state = user_data;
+
+	g_hash_table_unref (state->entities);
+}
+
+static void
+lsm_dom_parser_start_element(void *user_data,
+			     const xmlChar *name,
+			     const xmlChar **attrs)
+{
+	LsmDomSaxParserState *state = user_data;
+	LsmDomNode *node;
+	int i;
+
+	if (state->is_error) {
+		state->error_depth++;
+		return;
+	}
+
+	if (state->document == NULL) {
+		state->document = lsm_dom_implementation_create_document (NULL, (char *) name);
+		state->current_node = LSM_DOM_NODE (state->document);
+
+		g_return_if_fail (LSM_IS_DOM_DOCUMENT (state->document));
+	}
+
+	node = LSM_DOM_NODE (lsm_dom_document_create_element (LSM_DOM_DOCUMENT (state->document), (char *) name));
+
+	if (LSM_IS_DOM_NODE (node) && lsm_dom_node_append_child (state->current_node, node) != NULL) {
+		if (attrs != NULL)
+			for (i = 0; attrs[i] != NULL && attrs[i+1] != NULL; i += 2)
+				lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (node),
+							       (char *) attrs[i],
+							       (char *) attrs[i+1]);
+
+		state->current_node = node;
+		state->is_error = FALSE;
+		state->error_depth = 0;
+	} else {
+		state->is_error = TRUE;
+		state->error_depth = 1;
+	}
+}
+
+static void
+lsm_dom_parser_end_element (void *user_data,
+			    const xmlChar *name)
+{
+	LsmDomSaxParserState *state = user_data;
+
+	if (state->is_error) {
+		state->error_depth--;
+		if (state->error_depth > 0) {
+			return;
+		}
+
+		state->is_error = FALSE;
+		return;
+	}
+
+	state->current_node = lsm_dom_node_get_parent_node (state->current_node);
+}
+
+static void
+lsm_dom_parser_characters (void *user_data, const xmlChar *ch, int len)
+{
+	LsmDomSaxParserState *state = user_data;
+
+	if (!state->is_error) {
+		LsmDomNode *node;
+		char *text;
+
+		text = g_strndup ((char *) ch, len);
+		node = LSM_DOM_NODE (lsm_dom_document_create_text_node (LSM_DOM_DOCUMENT (state->document), text));
+
+		lsm_dom_node_append_child (state->current_node, node);
+
+		g_free (text);
+	}
+}
+
+static xmlEntityPtr
+lsm_dom_parser_get_entity (void *user_data, const xmlChar *name)
+{
+	LsmDomSaxParserState *state = user_data;
+	xmlEntity *entity;
+	const char *utf8;
+
+	entity = g_hash_table_lookup (state->entities, name);
+	if (entity != NULL)
+		return entity;
+
+	utf8 = lsm_mathml_entity_get_utf8 ((char *) name);
+	if (utf8 != NULL) {
+		entity = xmlNewEntity (NULL, name, XML_INTERNAL_GENERAL_ENTITY, NULL, NULL, (xmlChar *) utf8);
+
+		g_hash_table_insert (state->entities, (char *) name, entity);
+
+		return entity;
+	}
+
+	return xmlGetPredefinedEntity(name);
+}
+
+void
+lsm_dom_parser_declare_entity (void * user_data, const xmlChar * name, int type,
+			       const xmlChar * publicId, const xmlChar * systemId,
+			       xmlChar * content)
+{
+	LsmDomSaxParserState *state = user_data;
+
+	if (content != NULL) {
+		xmlEntity *entity;
+
+		entity = xmlNewEntity (NULL, name, type, publicId, systemId, content);
+
+		g_hash_table_insert (state->entities, (char *) name, entity);
+	}
+}
+
+#if 1
+static void
+lsm_dom_parser_warning (void *user_data, const char *msg, ...)
+{
+	va_list args;
+
+	va_start(args, msg);
+	g_logv("XML", G_LOG_LEVEL_WARNING, msg, args);
+	va_end(args);
+}
+
+static void
+lsm_dom_parser_error (void *user_data, const char *msg, ...)
+{
+	va_list args;
+
+	va_start(args, msg);
+	g_logv("XML", G_LOG_LEVEL_CRITICAL, msg, args);
+	va_end(args);
+}
+
+static void
+lsm_dom_parser_fatal_error (void *user_data, const char *msg, ...)
+{
+	va_list args;
+
+	va_start(args, msg);
+	g_logv("XML", G_LOG_LEVEL_ERROR, msg, args);
+	va_end(args);
+}
+#endif
+
+static xmlSAXHandler sax_handler = {
+#if 1
+	.warning = lsm_dom_parser_warning,
+	.error = lsm_dom_parser_error,
+	.fatalError = lsm_dom_parser_fatal_error,
+#endif
+	.startDocument = lsm_dom_parser_start_document,
+	.endDocument = lsm_dom_parser_end_document,
+	.startElement = lsm_dom_parser_start_element,
+	.endElement = lsm_dom_parser_end_element,
+	.characters = lsm_dom_parser_characters,
+	.getEntity = lsm_dom_parser_get_entity,
+	.entityDecl = lsm_dom_parser_declare_entity
+};
+
+static GQuark
+lsm_dom_document_error_quark (void)
+{
+	static GQuark q = 0;
+
+        if (q == 0) {
+                q = g_quark_from_static_string ("lsm-dom-error-quark");
+        }
+
+        return q;
+}
+
+#define LSM_DOM_DOCUMENT_ERROR lsm_dom_document_error_quark ()
+
+typedef enum {
+	LSM_DOM_DOCUMENT_ERROR_INVALID_XML
+} LsmDomDocumentError;
+
+LsmDomDocument *
+lsm_dom_document_new_from_memory (const void *buffer, int size, GError **error)
+{
+	static LsmDomSaxParserState state;
+
+	g_return_val_if_fail (buffer != NULL, NULL);
+
+	state.document = NULL;
+
+	if (size < 0)
+		size = strlen (buffer);
+
+	if (xmlSAXUserParseMemory (&sax_handler, &state, buffer, size) < 0) {
+		if (state.document !=  NULL)
+			g_object_unref (state.document);
+		state.document = NULL;
+
+		lsm_debug_dom ("[LsmDomParser::from_memory] Invalid document");
+
+		g_set_error (error,
+			     LSM_DOM_DOCUMENT_ERROR,
+			     LSM_DOM_DOCUMENT_ERROR_INVALID_XML,
+			     "Invalid document.");
+	}
+
+	return state.document;
+}
+
+static LsmDomDocument *
+lsm_dom_document_new_from_file (GFile *file, GError **error)
+{
+	LsmDomDocument *document;
+	gsize size = 0;
+	char *contents = NULL;
+
+	if (!g_file_load_contents (file, NULL, &contents, &size, NULL, error))
+		return NULL;
+
+	document = lsm_dom_document_new_from_memory (contents, size, error);
+
+	g_free (contents);
+
+	return document;
+}
+
+LsmDomDocument *
+lsm_dom_document_new_from_path (const char *path, GError **error)
+{
+	LsmDomDocument *document;
+	GFile *file;
+
+	g_return_val_if_fail (path != NULL, NULL);
+
+	file = g_file_new_for_path (path);
+
+	document = lsm_dom_document_new_from_file (file, error);
+
+	g_object_unref (file);
+
+	if (document != NULL)
+		lsm_dom_document_set_path (document, path);
+
+	return document;
+}
+
+LsmDomDocument *
+lsm_dom_document_new_from_url (const char *url, GError **error)
+{
+	LsmDomDocument *document;
+	GFile *file;
+
+	g_return_val_if_fail (url != NULL, NULL);
+
+	file = g_file_new_for_uri (url);
+
+	document = lsm_dom_document_new_from_file (file, error);
+
+	g_object_unref (file);
+
+	if (document != NULL)
+		lsm_dom_document_set_url (document, url);
+
+	return document;
+}
+
+void
+lsm_dom_document_save_to_stream (LsmDomDocument *document, GOutputStream *stream, GError **error)
+{
+	g_return_if_fail (LSM_IS_DOM_DOCUMENT (document));
+	g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
+
+	lsm_dom_node_write_to_stream (LSM_DOM_NODE (document), stream, error);
+}
+
+void
+lsm_dom_document_save_to_memory	(LsmDomDocument *document, void **buffer, int *size, GError **error)
+{
+	GOutputStream *stream;
+
+	if (buffer != NULL)
+		*buffer = NULL;
+	if (size != NULL)
+		*size = 0;
+
+	g_return_if_fail (document != NULL);
+	g_return_if_fail (buffer != NULL);
+
+	stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
+	if (stream == NULL) {
+		*buffer = NULL;
+		if (size != NULL)
+			*size = 0;
+		return;
+	}
+
+	lsm_dom_document_save_to_stream (document, G_OUTPUT_STREAM (stream), error);
+	g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, error);
+
+	if (size != NULL)
+		*size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (stream));
+	*buffer = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (stream));
+
+	g_object_unref (stream);
+}
+
+void
+lsm_dom_document_save_to_path (LsmDomDocument *document, const char *path, GError **error)
+{
+	GFile *file;
+	GFileOutputStream *stream;
+
+	g_return_if_fail (path != NULL);
+
+	file = g_file_new_for_path (path);
+	stream = g_file_create (file, G_FILE_CREATE_REPLACE_DESTINATION, NULL, error);
+	if (stream != NULL) {
+		lsm_dom_document_save_to_stream (document, G_OUTPUT_STREAM (stream), error);
+		g_object_unref (stream);
+	}
+	g_object_unref (file);
+}
+
+void
+lsm_dom_document_save_to_url (LsmDomDocument *document, const char *path, GError **error)
+{
+	GFile *file;
+	GFileOutputStream *stream;
+
+	g_return_if_fail (path != NULL);
+
+	file = g_file_new_for_uri (path);
+	stream = g_file_create (file, G_FILE_CREATE_REPLACE_DESTINATION, NULL, error);
+	if (stream != NULL) {
+		lsm_dom_document_save_to_stream (document, G_OUTPUT_STREAM (stream), error);
+		g_object_unref (stream);
+	}
+	g_object_unref (file);
+}
diff --git a/src/lsmdomparser.h b/src/lsmdomparser.h
new file mode 100644
index 0000000..5ff6b6c
--- /dev/null
+++ b/src/lsmdomparser.h
@@ -0,0 +1,52 @@
+/* Lasem
+ *
+ * Copyright  2007-2009 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_DOM_PARSER_H
+#define LSM_DOM_PARSER_H
+
+#include <lsmdomdocument.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+LsmDomDocument * 	lsm_dom_document_new_from_memory 	(const void *buffer, int size, GError **error);
+LsmDomDocument * 	lsm_dom_document_new_from_path 		(const char *path, GError **error);
+LsmDomDocument * 	lsm_dom_document_new_from_url 		(const char *url, GError **error);
+
+void			lsm_dom_document_save_to_stream		(LsmDomDocument *document,
+								 GOutputStream *stream,
+								 GError **error);
+void			lsm_dom_document_save_to_memory		(LsmDomDocument *documennt,
+								 void **buffer,
+								 int *size,
+								 GError **error);
+void			lsm_dom_document_save_to_path		(LsmDomDocument *documennt,
+								 const char *path,
+								 GError **error);
+void			lsm_dom_document_save_to_url		(LsmDomDocument *documennt,
+								 const char *path,
+								 GError **error);
+
+G_END_DECLS
+
+#endif
diff --git a/src/lsmdomtext.c b/src/lsmdomtext.c
new file mode 100644
index 0000000..dec4dc3
--- /dev/null
+++ b/src/lsmdomtext.c
@@ -0,0 +1,82 @@
+/* Lasem
+ *
+ * Copyright  2007-2008 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+/**
+ * SECTION:lsmdomtext
+ * @short_description: Base class for DOM text nodes
+ */
+
+#include <lsmdomtext.h>
+
+/* LsmDomNode implementation */
+
+static const char *
+lsm_dom_text_get_node_name (LsmDomNode *node)
+{
+	return "#text";
+}
+
+static const char *
+lsm_dom_text_get_node_value (LsmDomNode *node)
+{
+	return LSM_DOM_CHARACTER_DATA (node)->data;
+}
+
+static LsmDomNodeType
+lsm_dom_text_get_node_type (LsmDomNode *node)
+{
+	return LSM_DOM_NODE_TYPE_TEXT_NODE;
+}
+
+/* LsmDomText implementation */
+
+LsmDomNode *
+lsm_dom_text_new (const char *data)
+{
+	LsmDomNode *node;
+
+	node = g_object_new (LSM_TYPE_DOM_TEXT, NULL);
+
+	lsm_dom_character_data_set_data (LSM_DOM_CHARACTER_DATA (node), data);
+
+	return node;
+}
+
+static void
+lsm_dom_text_init (LsmDomText *text_node)
+{
+}
+
+/* LsmDomText class */
+
+static void
+lsm_dom_text_class_init (LsmDomTextClass *klass)
+{
+	LsmDomNodeClass *node_class = LSM_DOM_NODE_CLASS (klass);
+
+	node_class->get_node_name = lsm_dom_text_get_node_name;
+	node_class->get_node_value = lsm_dom_text_get_node_value;
+	node_class->get_node_type = lsm_dom_text_get_node_type;
+}
+
+G_DEFINE_TYPE (LsmDomText, lsm_dom_text, LSM_TYPE_DOM_CHARACTER_DATA)
diff --git a/src/lsmdomtext.h b/src/lsmdomtext.h
new file mode 100644
index 0000000..a793347
--- /dev/null
+++ b/src/lsmdomtext.h
@@ -0,0 +1,55 @@
+/* Lasem
+ *
+ * Copyright  2007-2008 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_DOM_TEXT_H
+#define LSM_DOM_TEXT_H
+
+#include <lsmdomcharacterdata.h>
+
+G_BEGIN_DECLS
+
+#define LSM_TYPE_DOM_TEXT             (lsm_dom_text_get_type ())
+#define LSM_DOM_TEXT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_DOM_TEXT, LsmDomText))
+#define LSM_DOM_TEXT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_DOM_TEXT, LsmDomTextClass))
+#define LSM_IS_DOM_TEXT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_DOM_TEXT))
+#define LSM_IS_DOM_TEXT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_DOM_TEXT))
+#define LSM_DOM_TEXT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_DOM_TEXT, LsmDomTextClass))
+
+typedef struct _LsmDomTextClass LsmDomTextClass;
+
+struct _LsmDomText {
+	LsmDomCharacterData	character_data;
+};
+
+struct _LsmDomTextClass {
+	LsmDomCharacterDataClass  parent_class;
+};
+
+GType lsm_dom_text_get_type (void);
+
+LsmDomNode 	*lsm_dom_text_new 		(const char *data);
+
+G_END_DECLS
+
+#endif
+
diff --git a/src/lsmdomtypes.h b/src/lsmdomtypes.h
new file mode 100644
index 0000000..1c71b1d
--- /dev/null
+++ b/src/lsmdomtypes.h
@@ -0,0 +1,44 @@
+/* Lasem - SVG and Mathml library
+ *
+ * Copyright  2010 Emmanuel Pacaud
+ *
+ * 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 2 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef LSM_DOM_TYPES_H
+#define LSM_DOM_TYPES_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _LsmDomNode LsmDomNode;
+typedef struct _LsmDomNodeList LsmDomNodeList;
+typedef struct _LsmDomNamedNodeMap LsmDomNamedNodeMap;
+typedef struct _LsmDomElement LsmDomElement;
+typedef struct _LsmDomDocument LsmDomDocument;
+typedef struct _LsmDomDocumentFragment LsmDomDocumentFragment;
+typedef struct _LsmDomCharacterData LsmDomCharacterData;
+typedef struct _LsmDomText LsmDomText;
+
+typedef struct _LsmDomView LsmDomView;
+
+G_END_DECLS
+
+#endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]