summaryrefslogtreecommitdiff
path: root/src/xml.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xml.c')
-rw-r--r--src/xml.c574
1 files changed, 574 insertions, 0 deletions
diff --git a/src/xml.c b/src/xml.c
new file mode 100644
index 0000000..baa4eb2
--- /dev/null
+++ b/src/xml.c
@@ -0,0 +1,574 @@
+
+/* Firebox Tools - Outils de configurations pour le WM Firebox
+ * xml.c - lecture ou écriture de documents XML
+ *
+ * Copyright (C) 2006-2007 Cyrille Bagard
+ *
+ * This file is part of Firebox Tools.
+ *
+ * Firebox Tools is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Firebox Tools 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "xml.h"
+
+
+#include <stdarg.h>
+#include <string.h>
+
+
+#ifdef DEBUG
+# define XML_LOG fprintf
+#else
+# define XML_LOG if (FALSE) fprintf
+#endif
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* OPERATIONS DE LECTURE D'UN FICHIER XML */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* Retour : true si l'opération a pu s'effectuer, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+gboolean open_xml_file(const char *filename, xmlDoc **xdoc, xmlNode **xroot, xmlXPathContextPtr *xpathCtx)
+{
+ *xdoc = xmlParseFile(filename);
+
+ if (*xdoc == NULL)
+ {
+ XML_LOG(stderr, "Can not parse the XML file '%s'\n", filename);
+ 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)
+ {
+ XML_LOG(stderr, "Unable to create new XPath context\n");
+ xmlFreeDoc(*xdoc);
+ return FALSE;
+ }
+
+ return TRUE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : xpathCtx = contexte à utiliser pour les recherches. *
+* path = chemin d'accès au noeud visé. *
+* *
+* Description : Obtient de façon encadrée l'accès à un noeud défini. *
+* *
+* Retour : Adresse de l'accès trouvé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+xmlXPathObjectPtr get_node_xpath_object(xmlXPathContextPtr xpathCtx, const char *path)
+{
+ xmlXPathObjectPtr result; /* Noeud XML à renvoyer */
+
+ result = xmlXPathEvalExpression(BAD_CAST path, xpathCtx);
+
+ if (result == NULL)
+ {
+ XML_LOG(stderr, "Unable to evaluate xpath expression '%s'\n", path);
+ return NULL;
+ }
+
+ if (result->nodesetval == NULL)
+ {
+ XML_LOG(stderr, "Node '%s' not found\n", path);
+ xmlXPathFreeObject(result);
+ return NULL;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = noeud dont une propriété est à lire. *
+* *
+* Description : Obtient une valeur placée entre <...> et </...>. *
+* *
+* Retour : Valeur sous forme de chaîne de caractères ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *qck_get_node_text_value(xmlNodePtr node)
+{
+ char *result; /* Valeur en question renvoyée */
+
+ result = NULL;
+
+ if (node != NULL)
+ if (node->children != NULL)
+ if (node->children->content != NULL)
+ result = strdup((char *)node->children->content);
+
+ if (result == NULL) XML_LOG(stderr, "No text value for node '%s'\n", node->name);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : xpathCtx = contexte à utiliser pour les recherches. *
+* path = chemin d'accès au noeud visé. *
+* *
+* Description : Obtient une valeur placée entre <...> et </...>. *
+* *
+* Retour : Valeur sous forme de chaîne de caractères ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *get_node_text_value(xmlXPathContextPtr xpathCtx, const char *path)
+{
+ char *result; /* Valeur en question renvoyée */
+ xmlXPathObjectPtr xpathObj; /* Point de départ XML */
+
+ result = NULL;
+
+ xpathObj = get_node_xpath_object(xpathCtx, path);
+ if (xpathObj == NULL) return NULL;
+
+ if (xpathObj->nodesetval->nodeNr > 0)
+ result = qck_get_node_text_value(xpathObj->nodesetval->nodeTab[0]);
+
+ xmlXPathFreeObject(xpathObj);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = noeud dont une propriété est à lire. *
+* name = nom de la propriété à lire. *
+* *
+* Description : Obtient la valeur d'une propriété d'un élément. *
+* *
+* Retour : Valeur sous forme de chaîne de caractères ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *qck_get_node_prop_value(xmlNodePtr node, const char *name)
+{
+ char *result; /* Valeur en question renvoyée */
+ xmlAttrPtr attrib; /* Liste d'attributs présents */
+
+ result = NULL;
+
+ if (node == NULL) return NULL;
+
+ /* Lecture de la valeur */
+
+ for (attrib = node->properties; attrib != NULL && result == NULL; attrib = attrib->next)
+ if (xmlStrEqual(attrib->name, BAD_CAST name)) result = strdup((char *)attrib->children->content);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : xpathCtx = contexte à utiliser pour les recherches. *
+* path = chemin d'accès au noeud à traiter. *
+* name = nom de la propriété à lire. *
+* *
+* Description : Obtient la valeur d'une propriété d'un élément. *
+* *
+* Retour : Valeur sous forme de chaîne de caractères ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *get_node_prop_value(xmlXPathContextPtr xpathCtx, const char *path, const char *name)
+{
+ char *result; /* Valeur en question renvoyée */
+ xmlXPathObjectPtr xpathObj; /* Point de départ XML */
+
+ result = NULL;
+
+ xpathObj = get_node_xpath_object(xpathCtx, path);
+ if (xpathObj == NULL) return NULL;
+
+ if (xpathObj->nodesetval->nodeNr > 0)
+ result = qck_get_node_prop_value(xpathObj->nodesetval->nodeTab[0], name);
+
+ xmlXPathFreeObject(xpathObj);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : node = noeud de texte avec un lien avec le document XML. *
+* *
+* Description : Construit un chemin d'accès complet selon le fichier XML. *
+* *
+* Retour : Valeur à libérer de la mémoire après usage ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *qck_build_filename_with_doc_url(xmlNodePtr node)
+{
+ char *result; /* Construction à retourner */
+ char *text; /* Valeur du texte lu */
+ char *last; /* Point de remplacement */
+
+ result = NULL;
+
+ text = qck_get_node_text_value(node);
+
+ if (text != NULL)
+ {
+ result = (char *)calloc(xmlStrlen(node->doc->URL) + strlen(text) + 1, sizeof(char));
+
+ strcpy(result, (const char *)node->doc->URL);
+
+ last = strrchr(result, '/');
+ last++;
+
+ strcpy(last, text);
+ free(text);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : xpathCtx = contexte à utiliser pour les recherches. *
+* path = chemin d'accès au noeud à traiter. *
+* *
+* Description : Construit un chemin d'accès complet selon le fichier XML. *
+* *
+* Retour : Valeur sous forme de chaîne de caractères ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *build_filename_with_doc_url(xmlXPathContextPtr xpathCtx, const char *path)
+{
+ char *result; /* Valeur en question renvoyée */
+ xmlXPathObjectPtr xpathObj; /* Point de départ XML */
+
+ result = NULL;
+
+ xpathObj = get_node_xpath_object(xpathCtx, path);
+ if (xpathObj == NULL) return NULL;
+
+ if (xpathObj->nodesetval->nodeNr > 0)
+ result = qck_build_filename_with_doc_url(xpathObj->nodesetval->nodeTab[0]);
+
+ xmlXPathFreeObject(xpathObj);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* OPERATIONS D'ECRITURE D'UN FICHIER XML */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : filename = nom du fichier à ouvrir. *
+* *
+* Description : Amorce l'écriture d'un nouveau fichier XML. *
+* *
+* Retour : Rédacteur mis en place ou NULL en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+xmlTextWriterPtr start_writing_xml_file(const char *filename)
+{
+ xmlTextWriterPtr result; /* Moyen à retourner */
+ int retval; /* Bilan d'une opération */
+
+ result = xmlNewTextWriterFilename(filename, 0);
+
+ if (result == NULL)
+ {
+ XML_LOG(stderr, "Error creating the xml writer\n");
+ return NULL;
+ }
+
+ retval = xmlTextWriterStartDocument(result, NULL, "UTF-8", "yes");
+ if (retval < 0)
+ {
+ XML_LOG(stderr, "Error at xmlTextWriterStartDocument\n");
+ xmlFreeTextWriter(result);
+ return NULL;
+ }
+
+ retval = xmlTextWriterSetIndent(result, 1);
+ if (retval < 0)
+ {
+ XML_LOG(stderr, "Error setting indentation\n");
+ xmlFreeTextWriter(result);
+ return NULL;
+ }
+
+ retval = xmlTextWriterSetIndentString(result, BAD_CAST "\t");
+ if (retval < 0)
+ {
+ XML_LOG(stderr, "Error setting indentation string\n");
+ xmlFreeTextWriter(result);
+ return NULL;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : writer = rédacteur dédié à l'écriture. *
+* *
+* Description : Met fin à l'écriture d'un nouveau fichier XML. *
+* *
+* Retour : Bilan de l'opération : true ou false. *
+* *
+* Remarques : Ferme au besoin toutes les balises encore ouvertes. *
+* *
+******************************************************************************/
+
+bool end_writing_xml_file(xmlTextWriterPtr writer)
+{
+ int retval; /* Bilan de l'opération */
+
+ retval = xmlTextWriterEndDocument(writer);
+ if (retval < 0)
+ {
+ XML_LOG(stderr, "Error at xmlTextWriterEndDocument\n");
+ return false;
+ }
+
+ xmlFreeTextWriter(writer);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : writer = rédacteur dédié à l'écriture. *
+* name = nom de la balise à écrire. *
+* *
+* Description : Ecrit une balise et ne la referme pas. *
+* *
+* Retour : Bilan de l'opération : true ou false. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool open_xml_element(xmlTextWriterPtr writer, const char *name)
+{
+ int retval; /* Bilan de l'opération */
+
+ retval = xmlTextWriterStartElement(writer, BAD_CAST name);
+
+ if (retval < 0)
+ XML_LOG(stderr, "Error at xmlTextWriterWriteFormatElement\n");
+
+ return (retval >= 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : writer = rédacteur dédié à l'écriture. *
+* *
+* Description : Ferme la dernière balise laissée ouverte. *
+* *
+* Retour : Bilan de l'opération : true ou false. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool close_xml_element(xmlTextWriterPtr writer)
+{
+ int retval; /* Bilan de l'opération */
+
+ retval = xmlTextWriterEndElement(writer);
+
+ if (retval < 0)
+ XML_LOG(stderr, "Error at xmlTextWriterWriteFormatElement\n");
+
+ return (retval >= 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : writer = rédacteur dédié à l'écriture. *
+* name = nom de la balise à écrire. *
+* format = format de la chaîne à traiter. *
+* ... = informations à inscrire. *
+* *
+* Description : Ecrit une balise avec un contenu textuel. *
+* *
+* Retour : Bilan de l'opération : true ou false. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool write_xml_element_with_content(xmlTextWriterPtr writer, const char *name, const char *format, ...)
+{
+ va_list ap; /* Liste d'arguments variable */
+ int retval; /* Bilan de l'opération */
+
+ va_start(ap, format);
+
+ retval = xmlTextWriterWriteVFormatElement(writer, BAD_CAST name, format, ap);
+
+ if (retval < 0)
+ XML_LOG(stderr, "Error at xmlTextWriterWriteFormatElement\n");
+
+ va_end(ap);
+
+ return (retval >= 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : writer = rédacteur dédié à l'écriture. *
+* name = nom de l'attribut à écrire. *
+* format = format de la chaîne à traiter. *
+* ... = informations à inscrire. *
+* *
+* Description : Ecrit un attribut avec un contenu textuel. *
+* *
+* Retour : Bilan de l'opération : true ou false. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool write_xml_attribute(xmlTextWriterPtr writer, const char *name, const char *format, ...)
+{
+ va_list ap; /* Liste d'arguments variable */
+ int retval; /* Bilan de l'opération */
+
+ va_start(ap, format);
+
+ retval = xmlTextWriterWriteVFormatAttribute(writer, BAD_CAST name, format, ap);
+
+ if (retval < 0)
+ XML_LOG(stderr, "Error at xmlTextWriterWriteFormatElement\n");
+
+ va_end(ap);
+
+ return (retval >= 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : writer = rédacteur dédié à l'écriture. *
+* format = format de la chaîne à traiter. *
+* ... = informations à inscrire. *
+* *
+* Description : Ecrit un contenu textuel. *
+* *
+* Retour : Bilan de l'opération : true ou false. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool write_xml_content(xmlTextWriterPtr writer, const char *format, ...)
+{
+ va_list ap; /* Liste d'arguments variable */
+ int retval; /* Bilan de l'opération */
+
+ va_start(ap, format);
+
+ retval = xmlTextWriterWriteVFormatString(writer, format, ap);
+
+ if (retval < 0)
+ XML_LOG(stderr, "Error at xmlTextWriterWriteFormatElement\n");
+
+ va_end(ap);
+
+ return (retval >= 0);
+
+}