diff options
Diffstat (limited to 'src/xml.c')
-rw-r--r-- | src/xml.c | 257 |
1 files changed, 246 insertions, 11 deletions
@@ -29,6 +29,9 @@ #include <string.h> +#include "common/extstr.h" + + #ifdef DEBUG # define XML_LOG fprintf #else @@ -37,6 +40,88 @@ +/****************************************************************************** +* * +* Paramètres : filename = nom du fichier à ouvrir. * +* xdoc = structure XML chargée. [OUT] * +* context = contexte à utiliser pour les recherches. [OUT] * +* * +* Description : Crée un nouveau fichier XML. * +* * +* Retour : true si l'opération a pu s'effectuer, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool create_new_xml_file(xmlDocPtr *xdoc, xmlXPathContextPtr *context) +{ + *xdoc = xmlNewDoc(BAD_CAST "1.0"); + + if (*xdoc == NULL) + return false; + + *context = xmlXPathNewContext(*xdoc); + + if (*context == NULL) + { + xmlFreeDoc(*xdoc); + return false; + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : xdoc = structure XML chargée. * +* filename = nom du fichier à remplir. * +* * +* Description : Sauvegarde une structure XML dans un fichier. * +* * +* Retour : true si l'opération a pu s'effectuer, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool save_xml_file(xmlDocPtr xdoc, const char *filename) +{ + int ret; /* Bilan de l'appel */ + + ret = xmlSaveFormatFileEnc(filename, xdoc, "UTF-8", 1); + + return (ret != -1); + +} + + +/****************************************************************************** +* * +* Paramètres : xdoc = structure XML chargée à supprimer. * +* context = contexte utilisé pour les recherches. * +* * +* Description : Ferme une structure XML. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void close_xml_file(xmlDocPtr xdoc, xmlXPathContextPtr context) +{ + xmlXPathFreeContext(context); + xmlFreeDoc(xdoc); + + xmlCleanupParser(); + +} + + + /* ---------------------------------------------------------------------------------- */ /* OPERATIONS DE LECTURE D'UN FICHIER XML */ /* ---------------------------------------------------------------------------------- */ @@ -46,7 +131,6 @@ * * * Paramètres : filename = nom du fichier à ouvrir. * * xdoc = structure XML chargée. [OUT] * -* xroot = noeud premier de l'ensemble des définitions.[OUT] * * xpathCtx = contexte à utiliser pour les recherches. [OUT] * * * * Description : Ouvre un fichier XML de façon encadrée. * @@ -57,7 +141,7 @@ * * ******************************************************************************/ -gboolean open_xml_file(const char *filename, xmlDoc **xdoc, xmlNode **xroot, xmlXPathContextPtr *xpathCtx) +gboolean open_xml_file(const char *filename, xmlDoc **xdoc, xmlXPathContextPtr *xpathCtx) { *xdoc = xmlParseFile(filename); @@ -67,15 +151,6 @@ gboolean open_xml_file(const char *filename, xmlDoc **xdoc, xmlNode **xroot, xml return FALSE; } - *xroot = xmlDocGetRootElement(*xdoc); - - if (*xroot == NULL) - { - XML_LOG(stderr, "Can not access the root node in '%s'\n", filename); - xmlFreeDoc(*xdoc); - return FALSE; - } - *xpathCtx = xmlXPathNewContext(*xdoc); if (*xpathCtx == NULL) @@ -572,3 +647,163 @@ bool write_xml_content(xmlTextWriterPtr writer, const char *format, ...) return (retval >= 0); } + + + +/* ---------------------------------------------------------------------------------- */ +/* OPERATIONS D'ECRITURE D'UN FICHIER XML */ +/* ---------------------------------------------------------------------------------- */ + + + +/****************************************************************************** +* * +* Paramètres : context = contexte à utiliser pour les recherches. * +* path = chemin d'accès au noeud visé. * +* * +* Description : Fournit le premier noeud correspondant à un chemin XPath. * +* * +* Retour : Adresse du noeud trouvé ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +xmlNodePtr get_node_from_xpath(xmlXPathContextPtr context, const char *path) +{ + xmlNodePtr result; /* Noeud trouvé à renvoyer */ + xmlXPathObjectPtr xobject; /* Point de départ XML */ + + result = NULL; + + xobject = get_node_xpath_object(context, path); + if (xobject == NULL) return NULL; + + if (xobject->nodesetval->nodeNr > 0) + result = xobject->nodesetval->nodeTab[0]; + + xmlXPathFreeObject(xobject); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : xdoc = structure XML chargée. * +* context = contexte à utiliser pour les recherches. * +* path = chemin d'accès au noeud visé. * +* * +* Description : S'assure qu'un noeud donné est bien présent dans le document.* +* * +* Retour : Noeud en question ou NULL en cas d'échec à la création. * +* * +* Remarques : - * +* * +******************************************************************************/ + +xmlNodePtr ensure_node_exist(xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path) +{ + xmlNodePtr result; /* Noeud à retourner */ + char **levels; /* Niveaux dans le chemin */ + size_t levels_count; /* Nombre de ces niveaux */ + xmlNodePtr last; /* Dernier noeud valide */ + size_t i; /* Boucle de parcours #1 */ + char *iter_path; /* Chamin d'accès pour le test */ + size_t j; /* Boucle de parcours #2 */ + xmlNodePtr iter; /* Test d'accès à un noeud */ + char *cond; /* Marque de condition ('[') */ + + result = get_node_from_xpath(context, path); + + if (result == NULL) + { + levels = strtoka(path, "/", &levels_count); + + /* Recherche la racine valide la plus haute */ + + last = xmlDocGetRootElement(xdoc); + + for (i = 0; i < levels_count && last != NULL; i++) + { + iter_path = strdup(""); + + for (j = 0; j <= i; j++) + { + iter_path = stradd(iter_path, "/"); + iter_path = stradd(iter_path, levels[j]); + } + + iter = get_node_from_xpath(context, iter_path); + + if (iter == NULL) break; + else last = iter; + + } + + /* Inscription des noeuds restants */ + + if (last == NULL) + { + last = xmlNewDocNode(xdoc, NULL, BAD_CAST levels[i++], NULL); + xmlDocSetRootElement(xdoc, last); + + if (i == levels_count) + result = last; + + } + + for ( ; i < levels_count && last != NULL; i++) + { + cond = strchr(levels[i], '['); + if (cond != NULL) *cond = '\0'; + + result = xmlNewDocNode(xdoc, NULL, BAD_CAST levels[i], NULL); + result = xmlAddChild(last, result); + last = result; + } + + /* Libération de la mémoire */ + + for (i = 0; i < levels_count; i++) + free(levels[i]); + + free(levels); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : xdoc = structure XML chargée. * +* context = contexte à utiliser pour les recherches. * +* path = chemin d'accès au noeud visé. * +* content = texte à inscrire en contenu. * +* * +* Description : S'assure qu'un noeud donné est bien présent dans le document.* +* * +* Retour : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool add_content_to_node(xmlDocPtr xdoc, xmlXPathContextPtr context, const char *path, const char *content) +{ + xmlNodePtr node; /* Noeud à modifier */ + + if (content == NULL) return true; + + node = ensure_node_exist(xdoc, context, path); + if (node == NULL) return false; + + xmlNodeSetContent(node, content); + + return true; + +} |