diff --git a/include/parsing.h b/include/parsing.h
new file mode 100644
index 0000000..3e28962
--- /dev/null
+++ b/include/parsing.h
@@ -0,0 +1,31 @@
+//=-------------------------------------------------------------------------=//
+// XML parsing module //
+// //
+// Copyright © 2021 The Gem-graph Project //
+// //
+// This file is part of gem-graph. //
+// //
+// This program is free software: you can redistribute it and/or modify //
+// it under the terms of the GNU Affero General Public License as //
+// published by the Free Software Foundation, either version 3 of the //
+// License, or (at your option) any later version. //
+// //
+// This program 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 Affero General Public License for more details. //
+// //
+// You should have received a copy of the GNU Affero General Public License //
+// along with this program. If not, see . //
+//=-------------------------------------------------------------------------=//
+
+#pragma once
+#ifndef BASE_H
+ #include "../include/base.h"
+#endif
+
+/* -------------------------------------------------------------------------- */
+
+int ParseModelXML(Model_t*);
+
+/* -------------------------------------------------------------------------- */
diff --git a/src/parsing.c b/src/parsing.c
new file mode 100644
index 0000000..4a9e4e7
--- /dev/null
+++ b/src/parsing.c
@@ -0,0 +1,137 @@
+//=-------------------------------------------------------------------------=//
+// XML parsing module //
+// //
+// Copyright © 2021 The Gem-graph Project //
+// //
+// This file is part of gem-graph. //
+// //
+// This program is free software: you can redistribute it and/or modify //
+// it under the terms of the GNU Affero General Public License as //
+// published by the Free Software Foundation, either version 3 of the //
+// License, or (at your option) any later version. //
+// //
+// This program 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 Affero General Public License for more details. //
+// //
+// You should have received a copy of the GNU Affero General Public License //
+// along with this program. If not, see . //
+//=-------------------------------------------------------------------------=//
+
+#include "../include/base.h"
+
+#include
+#include
+#include
+#include
+
+/* -------------------------------------------------------------------------- */
+
+static int parseIdentityXML(Model_t*, xmlDocPtr, xmlNodePtr);
+ static int parseIdentityNameXML(Model_t*, xmlDocPtr, xmlNodePtr);
+
+// Table of all parsers
+struct parserTableXML_t {
+ const xmlChar *tag;
+ int (*execute) (Model_t*, xmlDocPtr, xmlNodePtr);
+} typedef ParserTableXML_t;
+
+static ParserTableXML_t toplevelParserTableXML[] =
+{
+ {(const xmlChar *)"identity", parseIdentityXML},
+};
+
+static ParserTableXML_t identityParserTableXML[] =
+{
+ {(const xmlChar *)"name", parseIdentityChildren},
+ {(const xmlChar *)"author", parseIdentityChildren},
+ {(const xmlChar *)"author_id", parseIdentityChildren},
+ {(const xmlChar *)"date", parseIdentityChildren},
+ {(const xmlChar *)"version", parseIdentityChildren},
+};
+
+/* -------------------------------------------------------------------------- */
+
+static int parseIdentityNameXML (Model_t *model, xmlDocPtr doc,
+ xmlNodePtr currentNode)
+{
+ xmlChar *key;
+ key = xmlNodeListGetString(doc, currentNode->xmlChildrenNode, 1);
+ printLog("key: %s\n", key);
+ xmlFree(key);
+ return 0;
+}
+
+static int parseIdentityXML (Model_t *model, xmlDocPtr doc,
+ xmlNodePtr currentNode)
+{
+ xmlChar *key;
+ currentNode = currentNode->xmlChildrenNode;
+ while (currentNode != NULL) {
+ for (int i = 0; i < LEN(identityParserTableXML); i++) {
+ if ((!xmlStrcmp(currentNode->name,
+ identityParserTableXML[i].tag))) {
+ identityParserTableXML[i].execute(model,
+ doc,
+ currentNode);
+ }
+ }
+ currentNode = currentNode->next;
+ }
+ return 0;
+}
+
+int ParseModelXML(Model_t *model)
+{
+ printLog("Parsing model %s\n", model->name);
+ xmlDocPtr xmlDocument;
+ xmlNodePtr currentNode;
+
+ xmlDocument = xmlParseFile(model->filename);
+
+ if (xmlDocument == NULL) {
+ printLog("Can't parse model file at '%s'.\n", model->filename);
+ return -1;
+ }
+
+ currentNode = xmlDocGetRootElement(xmlDocument);
+
+ if (currentNode == NULL) {
+ printLog("Invalid model file at '%s', document empty !\n",
+ model->filename);
+ xmlFreeDoc(xmlDocument);
+ return -2;
+ }
+
+ if (xmlStrcmp(currentNode->name, (const xmlChar *) "gem-graph-model")) {
+ printLog("Invalid model file at '%s', "
+ "root node is not !\n",
+ model->filename);
+ xmlFreeDoc(xmlDocument);
+ return -3;
+ }
+
+ currentNode = currentNode->xmlChildrenNode;
+ while (currentNode != NULL) {
+ for (int i = 0; i < LEN(toplevelParserTableXML); i++) {
+ if ((!xmlStrcmp(currentNode->name,
+ toplevelParserTableXML[i].tag))) {
+ toplevelParserTableXML[i].execute(model,
+ xmlDocument,
+ currentNode);
+ }
+ }
+
+ currentNode = currentNode->next;
+ }
+
+ xmlFreeDoc(xmlDocument);
+
+ // Interpret what needs to be
+ //model->date = strtol(date, NULL, 0);
+
+ // validate when we're finished
+ // model->validated = true;
+ return 0;
+}