OpenSync 0.22
opensync/opensync_xml.c
00001 /*
00002  * xml - A plugin for xml objects for the opensync framework
00003  * Copyright (C) 2004-2005  Armin Bauer <armin.bauer@opensync.org>
00004  * 
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  * 
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00018  * 
00019  */
00020  
00021 #include "opensync.h"
00022 #include "opensync_internals.h"
00023 
00024 xmlNode *osxml_node_add_root(xmlDoc *doc, const char *name)
00025 {
00026         doc->children = xmlNewDocNode(doc, NULL, (xmlChar*)name, NULL);
00027         return doc->children;
00028 }
00029 
00030 xmlNode *osxml_node_get_root(xmlDoc *doc, const char *name, OSyncError **error)
00031 {
00032         xmlNode *cur = xmlDocGetRootElement(doc);
00033         if (!cur) {
00034                 osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to get xml root element");
00035                 return NULL;
00036         }
00037         
00038         if (xmlStrcmp((cur)->name, (const xmlChar *) name)) {
00039                 osync_error_set(error, OSYNC_ERROR_GENERIC, "Wrong xml root element");
00040                 return NULL;
00041         }
00042         
00043         cur = (cur)->xmlChildrenNode;
00044         return cur;
00045 }
00046 
00047 void osxml_node_set(xmlNode *node, const char *name, const char *data, OSyncXMLEncoding encoding)
00048 {
00049         if (name)
00050                 xmlNodeSetName(node, (xmlChar*)name); //FIXME Free previous name?
00051                 
00052         if (data)
00053                 xmlNewTextChild(node, NULL, (xmlChar*)"Content", (xmlChar*)data);
00054 }
00055 
00056 xmlNode *osxml_node_add(xmlNode *parent, const char *name, const char *data)
00057 {
00058         if (!data)
00059                 return NULL;
00060         if (strlen(data) == 0)
00061                 return NULL;
00062         xmlNode *node = xmlNewTextChild(parent, NULL, (xmlChar*)name, (xmlChar*)data);
00063         return node;
00064 }
00065 
00066 void osxml_node_add_property(xmlNode *parent, const char *name, const char *data)
00067 {
00068         xmlNewProp(parent, (xmlChar*)name, (xmlChar*)data);
00069 }
00070 
00071 void osxml_node_mark_unknown(xmlNode *parent)
00072 {
00073         if (!xmlHasProp(parent, (xmlChar*)"Type"))
00074                 xmlNewProp(parent, (xmlChar*)"Type", (xmlChar*)"Unknown");
00075 }
00076 
00077 void osxml_node_remove_unknown_mark(xmlNode *node)
00078 {
00079         xmlAttr *attr = xmlHasProp(node, (xmlChar*)"Type");
00080         if (!attr)
00081                 return;
00082         xmlRemoveProp(attr);
00083 }
00084 
00085 xmlNode *osxml_get_node(xmlNode *parent, const char *name)
00086 {
00087         xmlNode *cur = (parent)->xmlChildrenNode;
00088         while (cur) {
00089                 if (!xmlStrcmp(cur->name, (const xmlChar *)name))
00090                         return cur;
00091                 cur = cur->next;
00092         }
00093         return NULL;
00094 }
00095 
00096 char *osxml_find_node(xmlNode *parent, const char *name)
00097 {
00098         return (char*)xmlNodeGetContent(osxml_get_node(parent, name));
00099 }
00100 
00101 xmlXPathObject *osxml_get_nodeset(xmlDoc *doc, const char *expression)
00102 {
00103         xmlXPathContext *xpathCtx = NULL;
00104         xmlXPathObject *xpathObj = NULL;
00105     
00106     /* Create xpath evaluation context */
00107     xpathCtx = xmlXPathNewContext(doc);
00108     if(xpathCtx == NULL) {
00109         fprintf(stderr,"Error: unable to create new XPath context\n");
00110         return NULL;
00111     }
00112     
00113     /* Evaluate xpath expression */
00114     xpathObj = xmlXPathEvalExpression((xmlChar*)expression, xpathCtx);
00115     if(xpathObj == NULL) {
00116         fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"\n", expression);
00117         xmlXPathFreeContext(xpathCtx); 
00118         return NULL;
00119     }
00120 
00121         xmlXPathFreeContext(xpathCtx);
00122         /* Cleanup of XPath data */
00123    // xmlXPathFreeObject(xpathObj);
00124    return xpathObj;
00125 }
00126 
00127 xmlXPathObject *osxml_get_unknown_nodes(xmlDoc *doc)
00128 {
00129         return osxml_get_nodeset(doc, "/*/*[@Type='Unknown']");
00130 }
00131 
00132 void osxml_map_unknown_param(xmlNode *node, const char *paramname, const char *newname)
00133 {
00134         xmlNode *cur = node->xmlChildrenNode;
00135         while (cur) {
00136                 if (xmlStrcmp(cur->name, (const xmlChar *)"UnknownParam"))
00137                         goto next;
00138                 
00139                 char *name = osxml_find_node(cur, "ParamName");
00140                 char *content = osxml_find_node(cur, "Content");
00141                 if (!strcmp(name, paramname)) {
00142                         osxml_node_add(node, newname, content);
00143                         osxml_node_remove_unknown_mark(node);
00144                         
00145                         xmlUnlinkNode(cur);
00146                         xmlFreeNode(cur);
00147                         g_free(name);
00148                         g_free(content);
00149                         return;
00150                 }
00151                 
00152                 g_free(name);
00153                 g_free(content);
00154                         
00155                 next:;
00156                 cur = cur->next;
00157         }
00158 }
00159 
00160 osync_bool osxml_has_property_full(xmlNode *parent, const char *name, const char *data)
00161 {
00162         if (osxml_has_property(parent, name))
00163                 return (strcmp((char*)xmlGetProp(parent, (xmlChar*)name), data) == 0);
00164         return FALSE;
00165 }
00166 
00167 char *osxml_find_property(xmlNode *parent, const char *name)
00168 {
00169         return (char*)xmlGetProp(parent, (xmlChar*)name);
00170 }
00171 
00172 osync_bool osxml_has_property(xmlNode *parent, const char *name)
00173 {
00174         return (xmlHasProp(parent, (xmlChar*)name) != NULL);
00175 }
00176 
00177 xmlChar *osxml_write_to_string(xmlDoc *doc)
00178 {
00179         xmlKeepBlanksDefault(0);
00180         xmlChar *temp = NULL;
00181         int size = 0;
00182         xmlDocDumpFormatMemoryEnc(doc, &temp, &size, NULL, 1);
00183         return temp;
00184 }
00185 
00186 osync_bool osxml_copy(const char *input, int inpsize, char **output, int *outpsize)
00187 {
00188         xmlDoc *doc = (xmlDoc *)(input);
00189         xmlDoc *newdoc = xmlCopyDoc(doc, TRUE);
00190         *output = (char *)newdoc;
00191         *outpsize = sizeof(newdoc);
00192         return TRUE;
00193 }
00194 
00195 osync_bool osxml_marshall(const char *input, int inpsize, char **output, int *outpsize, OSyncError **error)
00196 {
00197         xmlDoc *doc = (xmlDoc*)input;
00198         xmlChar *result;
00199         int size;
00200         xmlDocDumpMemory(doc, &result, &size);
00201         *output = (char*)result;
00202         *outpsize = size;
00203         return TRUE;
00204 }
00205 
00206 osync_bool osxml_demarshall(const char *input, int inpsize, char **output, int *outpsize, OSyncError **error)
00207 {
00208         xmlDoc *doc = xmlParseMemory(input, inpsize);
00209         if (!doc) {
00210                 osync_error_set(error, OSYNC_ERROR_GENERIC, "Invalid XML data received");
00211                 goto error;
00212         }
00213 
00214         *output = (char*)doc;
00215         *outpsize = sizeof(*doc);
00216         return TRUE;
00217 
00218 error:
00219         return FALSE;
00220 }
00221 
00222