xml.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003  -------------------
00004  cvs         : $Id$
00005  begin       : Sat Jun 28 2003
00006  copyright   : (C) 2003 by Martin Preuss
00007  email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00024  *   MA  02111-1307  USA                                                   *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031 
00032 #define DISABLE_DEBUGLOG
00033 
00034 #include "xml_p.h"
00035 #include "xmlctx_l.h"
00036 #include "i18n_l.h"
00037 
00038 #include <gwenhywfar/debug.h>
00039 #include <gwenhywfar/misc.h>
00040 #include <gwenhywfar/text.h>
00041 #include <gwenhywfar/path.h>
00042 #include <gwenhywfar/fastbuffer.h>
00043 #include <gwenhywfar/io_file.h>
00044 #include <gwenhywfar/io_memory.h>
00045 #include <gwenhywfar/io_buffered.h>
00046 #include <gwenhywfar/iomanager.h>
00047 
00048 #include <stdlib.h>
00049 #include <assert.h>
00050 #include <string.h>
00051 #include <ctype.h>
00052 #include <sys/types.h>
00053 #ifdef HAVE_SYS_STAT_H
00054 # include <sys/stat.h>
00055 #endif
00056 #ifdef HAVE_FCNTL_H
00057 # include <fcntl.h>
00058 #endif
00059 #include <errno.h>
00060 #ifdef HAVE_UNISTD_H
00061 # include <unistd.h>
00062 #endif
00063 
00064 
00065 #define GWEN_XML_BUFFERSIZE 512
00066 
00067 
00068 
00069 GWEN_LIST_FUNCTIONS(GWEN_XMLNODE, GWEN_XMLNode)
00070 GWEN_LIST2_FUNCTIONS(GWEN_XMLNODE, GWEN_XMLNode)
00071 
00072 GWEN_LIST_FUNCTIONS(GWEN_XMLNODE_NAMESPACE, GWEN_XMLNode_NameSpace)
00073 
00074 
00075 
00076 
00077 GWEN_XMLPROPERTY *GWEN_XMLProperty_new(const char *name, const char *value){
00078   GWEN_XMLPROPERTY *p;
00079 
00080   GWEN_NEW_OBJECT(GWEN_XMLPROPERTY, p);
00081   if (name)
00082     p->name=GWEN_Memory_strdup(name);
00083   if (value)
00084     p->value=GWEN_Memory_strdup(value);
00085   return p;
00086 }
00087 
00088 
00089 
00090 void GWEN_XMLProperty_free(GWEN_XMLPROPERTY *p){
00091   if (p) {
00092     GWEN_Memory_dealloc(p->name);
00093     GWEN_Memory_dealloc(p->value);
00094     GWEN_FREE_OBJECT(p);
00095   }
00096 }
00097 
00098 
00099 
00100 GWEN_XMLPROPERTY *GWEN_XMLProperty_dup(const GWEN_XMLPROPERTY *p){
00101   return GWEN_XMLProperty_new(p->name, p->value);
00102 }
00103 
00104 
00105 
00106 void GWEN_XMLProperty_add(GWEN_XMLPROPERTY *p, GWEN_XMLPROPERTY **head){
00107   GWEN_LIST_ADD(GWEN_XMLPROPERTY, p, head);
00108 }
00109 
00110 
00111 
00112 void GWEN_XMLProperty_insert(GWEN_XMLPROPERTY *p, GWEN_XMLPROPERTY **head){
00113   GWEN_LIST_INSERT(GWEN_XMLPROPERTY, p, head);
00114 }
00115 
00116 
00117 void GWEN_XMLProperty_del(GWEN_XMLPROPERTY *p, GWEN_XMLPROPERTY **head){
00118   GWEN_LIST_DEL(GWEN_XMLPROPERTY, p, head);
00119 }
00120 
00121 
00122 void GWEN_XMLProperty_freeAll(GWEN_XMLPROPERTY *p) {
00123   while(p) {
00124     GWEN_XMLPROPERTY *next;
00125 
00126     next=p->next;
00127     GWEN_XMLProperty_free(p);
00128     p=next;
00129   } /* while */
00130 }
00131 
00132 
00133 
00134 
00135 GWEN_XMLNODE *GWEN_XMLNode_new(GWEN_XMLNODE_TYPE t, const char *data){
00136   GWEN_XMLNODE *n;
00137 
00138   GWEN_NEW_OBJECT(GWEN_XMLNODE, n);
00139   GWEN_LIST_INIT(GWEN_XMLNODE, n);
00140   n->type=t;
00141   n->children=GWEN_XMLNode_List_new();
00142   n->headers=GWEN_XMLNode_List_new();
00143   if (data)
00144     n->data=GWEN_Memory_strdup(data);
00145   n->nameSpaces=GWEN_XMLNode_NameSpace_List_new();
00146   return n;
00147 }
00148 
00149 
00150 void GWEN_XMLNode_free(GWEN_XMLNODE *n){
00151   if (n) {
00152     GWEN_LIST_FINI(GWEN_XMLNODE, n);
00153     GWEN_XMLProperty_freeAll(n->properties);
00154     GWEN_Memory_dealloc(n->nameSpace);
00155     GWEN_Memory_dealloc(n->data);
00156     GWEN_XMLNode_List_free(n->headers);
00157     GWEN_XMLNode_List_free(n->children);
00158     GWEN_XMLNode_NameSpace_List_free(n->nameSpaces);
00159     GWEN_FREE_OBJECT(n);
00160   }
00161 }
00162 
00163 
00164 void GWEN_XMLNode_freeAll(GWEN_XMLNODE *n){
00165   while(n) {
00166     GWEN_XMLNODE *next;
00167 
00168     next=GWEN_XMLNode_List_Next(n);
00169     GWEN_XMLNode_free(n);
00170     n=next;
00171   } /* while */
00172 }
00173 
00174 
00175 GWEN_XMLNODE *GWEN_XMLNode_dup(const GWEN_XMLNODE *n){
00176   GWEN_XMLNODE *nn, *cn, *ncn;
00177   const GWEN_XMLPROPERTY *p;
00178   const GWEN_XMLNODE_NAMESPACE *nns;
00179 
00180   /* duplicate node itself */
00181   nn=GWEN_XMLNode_new(n->type, n->data);
00182   if (n->nameSpace)
00183     nn->nameSpace=strdup(n->nameSpace);
00184 
00185   /* duplicate properties */
00186   p=n->properties;
00187   while(p) {
00188     GWEN_XMLPROPERTY *np;
00189 
00190     np=GWEN_XMLProperty_dup(p);
00191     GWEN_XMLProperty_add(np, &(nn->properties));
00192     p=p->next;
00193   } /* while */
00194 
00195   /* duplicate children */
00196   cn=GWEN_XMLNode_List_First(n->children);
00197   while(cn) {
00198     ncn=GWEN_XMLNode_dup(cn);
00199     GWEN_XMLNode_AddChild(nn, ncn);
00200     cn=GWEN_XMLNode_Next(cn);
00201   } /* while */
00202 
00203   /* duplicate headers */
00204   cn=GWEN_XMLNode_List_First(n->headers);
00205   while(cn) {
00206     ncn=GWEN_XMLNode_dup(cn);
00207     GWEN_XMLNode_AddHeader(nn, ncn);
00208     cn=GWEN_XMLNode_Next(cn);
00209   } /* while */
00210 
00211   /* duplicate namespaces */
00212   nns=GWEN_XMLNode_NameSpace_List_First(n->nameSpaces);
00213   while(nns) {
00214     GWEN_XMLNODE_NAMESPACE *nnns;
00215 
00216     nnns=GWEN_XMLNode_NameSpace_dup(nns);
00217     GWEN_XMLNode_NameSpace_List_Add(nnns, nn->nameSpaces);
00218     nns=GWEN_XMLNode_NameSpace_List_Next(nns);
00219   }
00220 
00221   return nn;
00222 }
00223 
00224 
00225 
00226 const char *GWEN_XMLNode_GetProperty(const GWEN_XMLNODE *n, const char *name,
00227                                      const char *defaultValue){
00228   GWEN_XMLPROPERTY *p;
00229 
00230   assert(n);
00231   assert(name);
00232   p=n->properties;
00233   while(p) {
00234     assert(p->name);
00235     if (strcasecmp(p->name, name)==0)
00236       break;
00237     p=p->next;
00238   } /* while */
00239 
00240   if (p) {
00241     if (p->value)
00242       return p->value;
00243   }
00244   return defaultValue;
00245 }
00246 
00247 
00248 void GWEN_XMLNode__SetProperty(GWEN_XMLNODE *n,
00249                                const char *name, const char *value,
00250                                int doInsert){
00251   GWEN_XMLPROPERTY *p;
00252 
00253   p=n->properties;
00254   while(p) {
00255     assert(p->name);
00256     if (strcasecmp(p->name, name)==0)
00257       break;
00258     p=p->next;
00259   } /* while */
00260 
00261   if (p) {
00262     GWEN_Memory_dealloc(p->value);
00263     if (value)
00264       p->value=GWEN_Memory_strdup(value);
00265     else
00266       p->value=0;
00267   }
00268   else {
00269     p=GWEN_XMLProperty_new(name, value);
00270     if (doInsert)
00271       GWEN_XMLProperty_insert(p, &(n->properties));
00272     else
00273       GWEN_XMLProperty_add(p, &(n->properties));
00274   }
00275 }
00276 
00277 
00278 
00279 void GWEN_XMLNode_SetProperty(GWEN_XMLNODE *n,
00280                               const char *name, const char *value){
00281   GWEN_XMLNode__SetProperty(n, name, value, 0);
00282 }
00283 
00284 
00285 
00286 void GWEN_XMLNode_IncUsage(GWEN_XMLNODE *n){
00287   assert(n);
00288   n->usage++;
00289 }
00290 
00291 
00292 
00293 void GWEN_XMLNode_DecUsage(GWEN_XMLNODE *n){
00294   assert(n);
00295   if (n->usage==0) {
00296     DBG_WARN(GWEN_LOGDOMAIN, "Node usage already is zero");
00297   }
00298   else
00299     n->usage--;
00300 }
00301 
00302 
00303 
00304 uint32_t GWEN_XMLNode_GetUsage(const GWEN_XMLNODE *n){
00305   assert(n);
00306   return n->usage;
00307 }
00308 
00309 
00310 
00311 const char *GWEN_XMLNode_GetData(const GWEN_XMLNODE *n){
00312   assert(n);
00313   return n->data;
00314 }
00315 
00316 
00317 void GWEN_XMLNode_SetData(GWEN_XMLNODE *n, const char *data){
00318   assert(n);
00319   GWEN_Memory_dealloc(n->data);
00320   if (data)
00321     n->data=GWEN_Memory_strdup(data);
00322   else
00323     n->data=0;
00324 }
00325 
00326 
00327 
00328 const char *GWEN_XMLNode_GetNamespace(const GWEN_XMLNODE *n) {
00329   assert(n);
00330   return n->nameSpace;
00331 }
00332 
00333 
00334 
00335 void GWEN_XMLNode_SetNamespace(GWEN_XMLNODE *n, const char *s) {
00336   assert(n);
00337   GWEN_Memory_dealloc(n->nameSpace);
00338   if (s)
00339     n->nameSpace=GWEN_Memory_strdup(s);
00340   else
00341     n->nameSpace=NULL;
00342 }
00343 
00344 
00345 
00346 GWEN_XMLNODE *GWEN_XMLNode_GetChild(const GWEN_XMLNODE *n){
00347   assert(n);
00348   return GWEN_XMLNode_List_First(n->children);
00349 }
00350 
00351 
00352 GWEN_XMLNODE *GWEN_XMLNode_GetParent(const GWEN_XMLNODE *n){
00353   assert(n);
00354   return n->parent;
00355 }
00356 
00357 
00358 void GWEN_XMLNode_AddChild(GWEN_XMLNODE *n, GWEN_XMLNODE *child){
00359   assert(n);
00360   GWEN_XMLNode_List_Add(child, n->children);
00361   child->parent=n;
00362 }
00363 
00364 
00365 
00366 void GWEN_XMLNode_AddChildrenOnly(GWEN_XMLNODE *n, GWEN_XMLNODE *nn,
00367                                   int copythem){
00368   GWEN_XMLNODE *ch;
00369 
00370   assert(n);
00371   assert(nn);
00372 
00373   ch=GWEN_XMLNode_GetChild(nn);
00374   while(ch) {
00375     GWEN_XMLNODE *nc;
00376 
00377     nc=GWEN_XMLNode_Next(ch);
00378     if (!copythem) {
00379       GWEN_XMLNode_UnlinkChild(nn, ch);
00380       GWEN_XMLNode_AddChild(n, ch);
00381     }
00382     else {
00383       GWEN_XMLNode_AddChild(n, GWEN_XMLNode_dup(ch));
00384     }
00385     ch=nc;
00386   } /* while */
00387 }
00388 
00389 
00390 
00391 GWEN_XMLNODE_TYPE GWEN_XMLNode_GetType(const GWEN_XMLNODE *n){
00392   assert(n);
00393   return n->type;
00394 }
00395 
00396 
00397 GWEN_XMLNODE *GWEN_XMLNode_Next(const GWEN_XMLNODE *n) {
00398   assert(n);
00399   return GWEN_XMLNode_List_Next(n);
00400 }
00401 
00402 
00403 void GWEN_XMLNode_Dump(const GWEN_XMLNODE *n, FILE *f, int ind) {
00404   GWEN_XMLPROPERTY *p;
00405   GWEN_XMLNODE *c;
00406   int i;
00407   int simpleTag;
00408 
00409   assert(n);
00410 
00411   for(i=0; i<ind; i++)
00412     fprintf(f, " ");
00413 
00414   simpleTag=0;
00415   if (n->type==GWEN_XMLNodeTypeTag) {
00416     if (n->data)
00417       fprintf(f, "<%s", n->data);
00418     else
00419       fprintf(f, "<UNKNOWN");
00420     p=n->properties;
00421     while (p) {
00422       if (p->value)
00423         fprintf(f, " %s=\"%s\"", p->name, p->value);
00424       else
00425         fprintf(f, " %s", p->name);
00426       p=p->next;
00427     }
00428 
00429     if (n->data) {
00430       if (n->data[0]=='?') {
00431         simpleTag=1;
00432         fprintf(f, "?");
00433       }
00434       else if (n->data[0]=='!') {
00435         simpleTag=1;
00436       }
00437     }
00438 
00439     fprintf(f, ">\n");
00440     if (!simpleTag) {
00441       c=GWEN_XMLNode_GetChild(n);
00442       while(c) {
00443         GWEN_XMLNode_Dump(c, f, ind+2);
00444         c=GWEN_XMLNode_Next(c);
00445       }
00446       for(i=0; i<ind; i++)
00447         fprintf(f, " ");
00448       if (n->data)
00449         fprintf(f, "</%s>\n", n->data);
00450       else
00451         fprintf(f, "</UNKNOWN>\n");
00452     }
00453   }
00454   else if (n->type==GWEN_XMLNodeTypeData) {
00455     if (n->data) {
00456       fprintf(f, "%s\n", n->data);
00457     }
00458   }
00459   else if (n->type==GWEN_XMLNodeTypeComment) {
00460     fprintf(f, "<!--");
00461     if (n->data) {
00462       fprintf(f, "%s", n->data);
00463     }
00464     fprintf(f, "-->\n");
00465   }
00466   else {
00467     DBG_ERROR(GWEN_LOGDOMAIN, "Unknown tag type (%d)", n->type);
00468   }
00469 }
00470 
00471 
00472 
00473 GWEN_XMLNODE *GWEN_XMLNode_FindNode(const GWEN_XMLNODE *node,
00474                                     GWEN_XMLNODE_TYPE t, const char *data) {
00475   GWEN_XMLNODE *n;
00476 
00477   assert(node);
00478   assert(data);
00479 
00480   n=GWEN_XMLNode_GetChild(node);
00481   while(n) {
00482     if (n->type==t)
00483       if (n->data)
00484         if (strcasecmp(n->data, data)==0)
00485           break;
00486     n=GWEN_XMLNode_Next(n);
00487   } /* while */
00488 
00489   if (!n) {
00490     DBG_DEBUG(GWEN_LOGDOMAIN, "Node %d:\"%s\" not found", t, data);
00491     return 0;
00492   }
00493 
00494   return n;
00495 }
00496 
00497 
00498 
00499 void GWEN_XMLNode_UnlinkChild(GWEN_XMLNODE *n, GWEN_XMLNODE *child){
00500   assert(n);
00501   assert(child);
00502   GWEN_XMLNode_List_Del(child);
00503   child->parent=0;
00504 }
00505 
00506 
00507 
00508 void GWEN_XMLNode_RemoveChildren(GWEN_XMLNODE *n){
00509   assert(n);
00510   GWEN_XMLNode_List_Clear(n->children);
00511 }
00512 
00513 
00514 
00515 void GWEN_XMLNode_CopyProperties(GWEN_XMLNODE *tn,
00516                                  const GWEN_XMLNODE *sn,
00517                                  int overwrite){
00518   const GWEN_XMLPROPERTY *sp;
00519   GWEN_XMLPROPERTY *tp;
00520 
00521   assert(tn);
00522   assert(sn);
00523 
00524   sp=sn->properties;
00525   while(sp) {
00526     GWEN_XMLPROPERTY *np;
00527 
00528     assert(sp->name);
00529     tp=tn->properties;
00530     /* lookup property in target */
00531     while(tp) {
00532 
00533       assert(tp->name);
00534       if (strcasecmp(tp->name, sp->name)==0) {
00535         /* property already exists */
00536         if (overwrite) {
00537           /* overwrite old property */
00538           GWEN_Memory_dealloc(tp->value);
00539           tp->value=0;
00540           if (sp->value)
00541             tp->value=GWEN_Memory_strdup(sp->value);
00542         }
00543         break;
00544       }
00545       tp=tp->next;
00546     } /* while */
00547 
00548     if (!tp) {
00549       /* property not found, simply copy and add it */
00550       np=GWEN_XMLProperty_dup(sp);
00551       GWEN_XMLProperty_add(np, &(tn->properties));
00552     }
00553 
00554     sp=sp->next;
00555   } /* while */
00556 }
00557 
00558 
00559 
00560 GWEN_XMLNODE *GWEN_XMLNode_GetFirstOfType(const GWEN_XMLNODE *n,
00561                                           GWEN_XMLNODE_TYPE t){
00562   GWEN_XMLNODE *nn;
00563 
00564   assert(n);
00565   nn=GWEN_XMLNode_GetChild(n);
00566   while(nn) {
00567     if (nn->type==t)
00568       return nn;
00569     nn=GWEN_XMLNode_Next(nn);
00570   } /* while */
00571   return 0;
00572 }
00573 
00574 
00575 
00576 GWEN_XMLNODE *GWEN_XMLNode_GetNextOfType(const GWEN_XMLNODE *n,
00577                                          GWEN_XMLNODE_TYPE t){
00578   assert(n);
00579   while(n) {
00580     if (n->type==t)
00581       return (GWEN_XMLNODE *)n;
00582     n=GWEN_XMLNode_Next(n);
00583   } /* while */
00584   return 0;
00585 }
00586 
00587 
00588 
00589 GWEN_XMLNODE *GWEN_XMLNode_GetFirstTag(const GWEN_XMLNODE *n){
00590   return GWEN_XMLNode_GetFirstOfType(n, GWEN_XMLNodeTypeTag);
00591 }
00592 
00593 
00594 
00595 GWEN_XMLNODE *GWEN_XMLNode_GetNextTag(const GWEN_XMLNODE *n){
00596   GWEN_XMLNODE *next;
00597 
00598   next=GWEN_XMLNode_Next(n);
00599   if (!next)
00600     return 0;
00601   return GWEN_XMLNode_GetNextOfType(next, GWEN_XMLNodeTypeTag);
00602 }
00603 
00604 
00605 
00606 GWEN_XMLNODE *GWEN_XMLNode_GetFirstData(const GWEN_XMLNODE *n){
00607   return GWEN_XMLNode_GetFirstOfType(n, GWEN_XMLNodeTypeData);
00608 }
00609 
00610 
00611 
00612 GWEN_XMLNODE *GWEN_XMLNode_GetNextData(const GWEN_XMLNODE *n){
00613   GWEN_XMLNODE *next;
00614 
00615   next=GWEN_XMLNode_Next(n);
00616   if (!next)
00617     return 0;
00618   return GWEN_XMLNode_GetNextOfType(next, GWEN_XMLNodeTypeData);
00619 }
00620 
00621 
00622 
00623 GWEN_XMLNODE *GWEN_XMLNode_FindTag(const GWEN_XMLNODE *n,
00624                                    const char *tname,
00625                                    const char *pname,
00626                                    const char *pvalue){
00627   while(n) {
00628     if (-1!=GWEN_Text_ComparePattern(n->data, tname, 0)) {
00629       if (pname) {
00630         const char *p;
00631 
00632         p=GWEN_XMLNode_GetProperty(n, pname, 0);
00633         if (p) {
00634           if (!pvalue)
00635             return (GWEN_XMLNODE*)n;
00636           if (-1!=GWEN_Text_ComparePattern(pvalue, p, 0))
00637             return (GWEN_XMLNODE*)n;
00638         }
00639         else {
00640           /* return this node if pvalue is 0 an the property does not exist */
00641           if (!pvalue)
00642             return (GWEN_XMLNODE*)n;
00643         }
00644       } /* if pname */
00645       else
00646         return (GWEN_XMLNODE*)n;
00647     }
00648     n=GWEN_XMLNode_GetNextTag(n);
00649   } /* while */
00650   return 0;
00651 }
00652 
00653 
00654 
00655 GWEN_XMLNODE *GWEN_XMLNode_FindFirstTag(const GWEN_XMLNODE *n,
00656                                         const char *tname,
00657                                         const char *pname,
00658                                         const char *pvalue){
00659   GWEN_XMLNODE *nn;
00660 
00661   nn=GWEN_XMLNode_GetFirstTag(n);
00662   if (!nn)
00663     return 0;
00664   return GWEN_XMLNode_FindTag(nn,
00665                               tname,
00666                               pname,
00667                               pvalue);
00668 }
00669 
00670 
00671 
00672 GWEN_XMLNODE *GWEN_XMLNode_FindNextTag(const GWEN_XMLNODE *n,
00673                                        const char *tname,
00674                                        const char *pname,
00675                                        const char *pvalue){
00676   GWEN_XMLNODE *nn;
00677 
00678   nn=GWEN_XMLNode_GetNextTag(n);
00679   if (!nn)
00680     return 0;
00681   return GWEN_XMLNode_FindTag(nn,
00682                               tname,
00683                               pname,
00684                               pvalue);
00685 }
00686 
00687 
00688 
00689 const char *GWEN_XMLNode_GetCharValue(const GWEN_XMLNODE *n,
00690                                       const char *name,
00691                                       const char *defValue) {
00692   GWEN_XMLNODE *nn;
00693 
00694   nn=GWEN_XMLNode_FindFirstTag(n, name, 0, 0);
00695   while(nn) {
00696     GWEN_XMLNODE *dn;
00697 
00698     dn=GWEN_XMLNode_GetFirstData(nn);
00699     if (dn) {
00700       if (dn->data)
00701         return dn->data;
00702     }
00703     nn=GWEN_XMLNode_FindNextTag(nn, name, 0, 0);
00704   }
00705 
00706   return defValue;
00707 }
00708 
00709 
00710 
00711 const char *GWEN_XMLNode_GetLocalizedCharValue(const GWEN_XMLNODE *n,
00712                                                const char *name,
00713                                                const char *defValue) {
00714   GWEN_XMLNODE *nn=0;
00715   GWEN_STRINGLIST *langl;
00716 
00717   langl=GWEN_I18N_GetCurrentLocaleList();
00718   if (langl) {
00719     GWEN_STRINGLISTENTRY *se;
00720 
00721     se=GWEN_StringList_FirstEntry(langl);
00722     while(se) {
00723       const char *l;
00724 
00725       l=GWEN_StringListEntry_Data(se);
00726       DBG_DEBUG(GWEN_LOGDOMAIN, "Trying locale \"%s\"", l);
00727       assert(l);
00728       nn=GWEN_XMLNode_FindFirstTag(n, name, "lang", l);
00729       while(nn) {
00730         GWEN_XMLNODE *dn;
00731 
00732         dn=GWEN_XMLNode_GetFirstData(nn);
00733         if (dn) {
00734           if (dn->data && *(dn->data))
00735             return dn->data;
00736         }
00737         nn=GWEN_XMLNode_FindNextTag(nn, name, "lang", l);
00738       } /* while nn */
00739       se=GWEN_StringListEntry_Next(se);
00740     } /* while */
00741   } /* if language list available */
00742 
00743   /* otherwise try without locale */
00744   nn=GWEN_XMLNode_FindFirstTag(n, name, 0, 0);
00745   while(nn) {
00746     GWEN_XMLNODE *dn;
00747 
00748     dn=GWEN_XMLNode_GetFirstData(nn);
00749     if (dn) {
00750       if (dn->data)
00751         return dn->data;
00752     }
00753     nn=GWEN_XMLNode_FindNextTag(nn, name, 0, 0);
00754   }
00755 
00756   return defValue;
00757 }
00758 
00759 
00760 
00761 void GWEN_XMLNode_SetCharValue(GWEN_XMLNODE *n,
00762                                const char *name,
00763                                const char *value){
00764   GWEN_XMLNODE *nn;
00765 
00766   nn=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, name);
00767   if (value) {
00768     GWEN_XMLNODE *nnn;
00769 
00770     nnn=GWEN_XMLNode_new(GWEN_XMLNodeTypeData, value);
00771     GWEN_XMLNode_AddChild(nn, nnn);
00772   }
00773   GWEN_XMLNode_AddChild(n, nn);
00774 }
00775 
00776 
00777 
00778 int GWEN_XMLNode_GetIntValue(const GWEN_XMLNODE *n,
00779                              const char *name,
00780                              int defValue) {
00781   const char *p;
00782   int res;
00783 
00784   p=GWEN_XMLNode_GetCharValue(n, name, 0);
00785   if (!p)
00786     return defValue;
00787   if (1!=sscanf(p, "%i", &res))
00788     return defValue;
00789   return res;
00790 }
00791 
00792 
00793 
00794 void GWEN_XMLNode_SetIntValue(GWEN_XMLNODE *n,
00795                               const char *name,
00796                               int value){
00797   char numbuf[32];
00798 
00799   snprintf(numbuf, sizeof(numbuf)-1, "%d", value);
00800   numbuf[sizeof(numbuf)-1]=0;
00801   GWEN_XMLNode_SetCharValue(n, name, numbuf);
00802 }
00803 
00804 
00805 
00806 GWEN_XMLPROPERTY *GWEN_XMLNode_GetFirstProperty(const GWEN_XMLNODE *n){
00807   assert(n);
00808   return n->properties;
00809 }
00810 
00811 
00812 
00813 GWEN_XMLPROPERTY *GWEN_XMLNode_GetNextProperty(const GWEN_XMLNODE *n,
00814                                                const GWEN_XMLPROPERTY *pr){
00815   assert(n);
00816   assert(pr);
00817   return pr->next;
00818 }
00819 
00820 
00821 
00822 const char *GWEN_XMLProperty_GetName(const GWEN_XMLPROPERTY *pr){
00823   assert(pr);
00824   return pr->name;
00825 }
00826 
00827 
00828 
00829 const char *GWEN_XMLProperty_GetValue(const GWEN_XMLPROPERTY *pr){
00830   assert(pr);
00831   return pr->value;
00832 }
00833 
00834 
00835 
00836 int GWEN_XMLNode_IsChildOf(const GWEN_XMLNODE *parent,
00837                            const GWEN_XMLNODE *child) {
00838   GWEN_XMLNODE *n;
00839 
00840   if (!child || !parent || child==parent)
00841     return 0;
00842   n=child->parent;
00843   while(n) {
00844     if (n==parent)
00845       return 1;
00846     n=n->parent;
00847   }
00848   return 0;
00849 }
00850 
00851 
00852 
00853 int GWEN_XMLNode_GetXPath(const GWEN_XMLNODE *n1,
00854                           const GWEN_XMLNODE *n2,
00855                           GWEN_BUFFER *nbuf) {
00856   GWEN_BUFFER *lbuf;
00857   const GWEN_XMLNODE *ln1;
00858   const GWEN_XMLNODE *ln2;
00859 
00860   if (!n1 && !n2) {
00861     DBG_ERROR(GWEN_LOGDOMAIN, "Both nodes are NULL");
00862     return -1;
00863   }
00864 
00865   if (!n1) {
00866     n1=n2;
00867     while(n1->parent)
00868       n1=n1->parent;
00869   }
00870 
00871   if (!n2) {
00872     n2=n1;
00873     while(n2->parent)
00874       n2=n2->parent;
00875   }
00876 
00877   if (n2==n1) {
00878     GWEN_Buffer_AppendString(nbuf, "here()");
00879     return 0;
00880   }
00881 
00882   lbuf=GWEN_Buffer_new(0, 256, 0, 1);
00883   GWEN_Buffer_ReserveBytes(lbuf, 128);
00884 
00885   ln1=n1->parent;
00886   if (ln1) {
00887     GWEN_Buffer_AppendString(lbuf, "../");
00888     while(ln1) {
00889       if (ln1==n2) {
00890         /* found n2 */
00891         GWEN_Buffer_AppendBuffer(nbuf, lbuf);
00892         GWEN_Buffer_free(lbuf);
00893         return 0;
00894       }
00895       if (GWEN_XMLNode_IsChildOf(ln1, n2))
00896         break;
00897       ln1=ln1->parent;
00898       GWEN_Buffer_AppendString(lbuf, "../");
00899     }
00900 
00901     if (!ln1) {
00902       DBG_ERROR(GWEN_LOGDOMAIN, "Nodes do not share root node");
00903       GWEN_Buffer_free(lbuf);
00904       return -1;
00905     }
00906 
00907     /* append path to n1 */
00908     GWEN_Buffer_AppendBuffer(nbuf, lbuf);
00909   }
00910   DBG_ERROR(GWEN_LOGDOMAIN, "Path so far: %s", GWEN_Buffer_GetStart(lbuf));
00911 
00912   /* get path to n2 */
00913   GWEN_Buffer_Reset(lbuf);
00914 
00915   ln2=n2;
00916   while(ln2) {
00917     GWEN_XMLNODE *tn;
00918     int idx;
00919     char idxbuf[32];
00920 
00921     if (ln2->parent==ln1)
00922       break;
00923 
00924     /* count occurences of this tag in this level */
00925     idx=1;
00926     tn=ln2->parent;
00927     if (tn) {
00928       tn=GWEN_XMLNode_FindFirstTag(tn, ln2->data, 0, 0);
00929 
00930       while(tn) {
00931         if (tn==ln2)
00932           break;
00933         idx++;
00934         tn=GWEN_XMLNode_FindNextTag(tn, ln2->data, 0, 0);
00935       }
00936     }
00937 
00938     snprintf(idxbuf, sizeof(idxbuf), "[%d]", idx);
00939     idxbuf[sizeof(idxbuf)-1]=0;
00940     GWEN_Buffer_InsertString(lbuf, idxbuf);
00941     GWEN_Buffer_InsertString(lbuf, GWEN_XMLNode_GetData(ln2));
00942     GWEN_Buffer_InsertByte(lbuf, '/');
00943     ln2=ln2->parent;
00944   }
00945   DBG_ERROR(GWEN_LOGDOMAIN, "Path so far: %s", GWEN_Buffer_GetStart(lbuf));
00946   assert(ln2);
00947 
00948   /* append path to n2 */
00949   GWEN_Buffer_AppendBuffer(nbuf, lbuf);
00950   GWEN_Buffer_free(lbuf);
00951   return 0;
00952 }
00953 
00954 
00955 
00956 void* GWEN_XMLNode_HandlePath(const char *entry,
00957                               void *data,
00958                               int idx,
00959                               uint32_t flags) {
00960   GWEN_XMLNODE *n;
00961   GWEN_XMLNODE *nn;
00962   int i;
00963 
00964   n=(GWEN_XMLNODE*)data;
00965 
00966   if (flags & GWEN_PATH_FLAGS_VARIABLE) {
00967     DBG_ERROR(GWEN_LOGDOMAIN,
00968               "GWEN_PATH_FLAGS_VARIABLE not allowed for XPATH");
00969     return 0;
00970   }
00971 
00972   if (flags & GWEN_PATH_FLAGS_ROOT) {
00973     while(n->parent)
00974       n=n->parent;
00975     if (*entry=='/')
00976       entry++;
00977   }
00978 
00979   if (strcasecmp(entry, "..")==0) {
00980     return n->parent;
00981   }
00982   else if (strcasecmp(entry, ".")==0 ||
00983            strcasecmp(entry, "here()")==0) {
00984     return n;
00985   }
00986 
00987   /* check whether we are allowed to simply create the node */
00988   if (
00989       ((flags & GWEN_PATH_FLAGS_LAST) &&
00990        (((flags & GWEN_PATH_FLAGS_VARIABLE) &&
00991          (flags & GWEN_PATH_FLAGS_CREATE_VAR)) ||
00992         (!(flags & GWEN_PATH_FLAGS_VARIABLE) &&
00993          (flags & GWEN_PATH_FLAGS_CREATE_GROUP)))
00994       ) ||
00995       (
00996        !(flags & GWEN_PATH_FLAGS_LAST) &&
00997        (flags & GWEN_PATH_FLAGS_PATHCREATE))
00998      ) {
00999     /* simply create the new variable/group */
01000     if (flags & GWEN_PATH_FLAGS_VARIABLE) {
01001       /* not allowed for now */
01002       return 0;
01003     }
01004     else {
01005       if (idx!=0) {
01006         DBG_ERROR(GWEN_LOGDOMAIN,
01007                   "Can not create tag with index!=1 (%s)", entry);
01008         return 0;
01009       }
01010       DBG_VERBOUS(GWEN_LOGDOMAIN,
01011                   "Unconditionally creating tag \"%s\"", entry);
01012       nn=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, entry);
01013       GWEN_XMLNode_AddChild(n, nn);
01014       return nn;
01015     }
01016   }
01017 
01018   /* find the node */
01019   i=idx;
01020   nn=GWEN_XMLNode_FindFirstTag(n, entry, 0, 0);
01021   while(nn && i--) {
01022     nn=GWEN_XMLNode_FindNextTag(nn, entry, 0, 0);
01023   }
01024 
01025   if (!nn) {
01026     /* node not found, check, if we are allowed to create it */
01027     if (
01028         (!(flags & GWEN_PATH_FLAGS_LAST) &&
01029          (flags & GWEN_PATH_FLAGS_PATHMUSTEXIST)) ||
01030         (flags & GWEN_PATH_FLAGS_NAMEMUSTEXIST)
01031        ) {
01032       DBG_VERBOUS(GWEN_LOGDOMAIN,
01033                   "Tag \"%s\" does not exist", entry);
01034       return 0;
01035     }
01036     /* create the new variable/group */
01037     if (idx!=0) {
01038       DBG_ERROR(GWEN_LOGDOMAIN,
01039                 "Can not create tag with index!=1 (%s)", entry);
01040       return 0;
01041     }
01042     DBG_VERBOUS(GWEN_LOGDOMAIN,
01043                 "Tag \"%s\" not found, creating", entry);
01044     nn=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, entry);
01045     GWEN_XMLNode_AddChild(n, nn);
01046   } /* if node not found */
01047   else {
01048     /* node does exist, check whether this is ok */
01049     if (
01050         ((flags & GWEN_PATH_FLAGS_LAST) &&
01051          (flags & GWEN_PATH_FLAGS_NAMEMUSTNOTEXIST)) ||
01052         (!(flags & GWEN_PATH_FLAGS_LAST) &&
01053          (flags & GWEN_PATH_FLAGS_PATHMUSTNOTEXIST))
01054        ) {
01055       DBG_VERBOUS(GWEN_LOGDOMAIN, "Entry \"%s\" already exists", entry);
01056       return 0;
01057     }
01058   }
01059 
01060   return nn;
01061 }
01062 
01063 
01064 
01065 GWEN_XMLNODE *GWEN_XMLNode_GetNodeByXPath(GWEN_XMLNODE *n,
01066                                           const char *path,
01067                                           uint32_t flags){
01068   return (GWEN_XMLNODE*)GWEN_Path_HandleWithIdx(path,
01069                                                 (void*)n,
01070                                                 flags,
01071                                                 GWEN_XMLNode_HandlePath);
01072 }
01073 
01074 
01075 
01076 GWEN_XMLNODE *GWEN_XMLNode_GetHeader(const GWEN_XMLNODE *n){
01077   assert(n);
01078   return GWEN_XMLNode_List_First(n->headers);
01079 }
01080 
01081 
01082 
01083 void GWEN_XMLNode_AddHeader(GWEN_XMLNODE *n, GWEN_XMLNODE *nh){
01084   assert(n);
01085   assert(nh);
01086   GWEN_XMLNode_List_Add(nh, n->headers);
01087 }
01088 
01089 
01090 
01091 void GWEN_XMLNode_DelHeader(GWEN_XMLNODE *n, GWEN_XMLNODE *nh){
01092   assert(n);
01093   assert(nh);
01094   GWEN_XMLNode_List_Del(nh);
01095 }
01096 
01097 
01098 
01099 void GWEN_XMLNode_ClearHeaders(GWEN_XMLNODE *n){
01100   assert(n);
01101   GWEN_XMLNode_List_Clear(n->headers);
01102 }
01103 
01104 
01105 
01106 GWEN_XMLNODE_NAMESPACE_LIST *GWEN_XMLNode_GetNameSpaces(const GWEN_XMLNODE *n) {
01107   assert(n);
01108   return n->nameSpaces;
01109 }
01110 
01111 
01112 
01113 GWEN_XMLNODE_NAMESPACE *GWEN_XMLNode_FindNameSpaceByName(const GWEN_XMLNODE *n,
01114                                                          const char *s) {
01115   GWEN_XMLNODE_NAMESPACE *ns;
01116 
01117   assert(n);
01118   ns=GWEN_XMLNode_NameSpace_List_First(n->nameSpaces);
01119   while(ns) {
01120     const char *d;
01121 
01122     d=GWEN_XMLNode_NameSpace_GetName(ns);
01123     if (d && strcasecmp(d, s)==0)
01124       return ns;
01125     ns=GWEN_XMLNode_NameSpace_List_Next(ns);
01126   }
01127 
01128   return NULL;
01129 }
01130 
01131 
01132 
01133 GWEN_XMLNODE_NAMESPACE *GWEN_XMLNode_FindNameSpaceByUrl(const GWEN_XMLNODE *n,
01134                                                         const char *s) {
01135   GWEN_XMLNODE_NAMESPACE *ns;
01136 
01137   assert(n);
01138   ns=GWEN_XMLNode_NameSpace_List_First(n->nameSpaces);
01139   while(ns) {
01140     const char *d;
01141 
01142     d=GWEN_XMLNode_NameSpace_GetUrl(ns);
01143     if (d && strcasecmp(d, s)==0)
01144       return ns;
01145     ns=GWEN_XMLNode_NameSpace_List_Next(ns);
01146   }
01147 
01148   return NULL;
01149 }
01150 
01151 
01152 
01153 void GWEN_XMLNode_AddNameSpace(GWEN_XMLNODE *n, const GWEN_XMLNODE_NAMESPACE *ns) {
01154   assert(n);
01155   assert(ns);
01156   GWEN_XMLNode_NameSpace_List_Add(GWEN_XMLNode_NameSpace_dup(ns), n->nameSpaces);
01157 }
01158 
01159 
01160 
01161 
01162 
01163 
01164 
01165 
01166 
01167 
01168 
01169 int GWEN_XML_AddNameSpace(GWEN_STRINGLIST2 *sl,
01170                           const char *prefix,
01171                           const char *name){
01172   GWEN_BUFFER *nbuf;
01173   int rv;
01174 
01175   nbuf=GWEN_Buffer_new(0, 32, 0, 1);
01176   if (prefix)
01177     GWEN_Buffer_AppendString(nbuf, prefix);
01178   GWEN_Buffer_AppendByte(nbuf, ':');
01179   GWEN_Buffer_AppendString(nbuf, name);
01180   rv=GWEN_StringList2_AppendString(sl, GWEN_Buffer_GetStart(nbuf), 0,
01181                                    GWEN_StringList2_IntertMode_NoDouble);
01182   GWEN_Buffer_free(nbuf);
01183   return rv;
01184 }
01185 
01186 
01187 
01188 const char *GWEN_XML_FindNameSpaceByPrefix(GWEN_STRINGLIST2 *sl,
01189                                            const char *s){
01190   GWEN_STRINGLIST2_ITERATOR *it;
01191 
01192   it=GWEN_StringList2_First(sl);
01193   if (it) {
01194     const char *t;
01195 
01196     t=GWEN_StringList2Iterator_Data(it);
01197     assert(t);
01198     while(t) {
01199       const char *p;
01200 
01201       p=strchr(t, ':');
01202       assert(p);
01203       if ((s==0 && p==t) || (s && strncasecmp(t, s, p-t)==0))
01204         return t;
01205       t=GWEN_StringList2Iterator_Next(it);
01206     } /* while */
01207     GWEN_StringList2Iterator_free(it);
01208   }
01209   return 0;
01210 }
01211 
01212 
01213 
01214 const char *GWEN_XML_FindNameSpaceByName(GWEN_STRINGLIST2 *sl,
01215                                          const char *s){
01216   GWEN_STRINGLIST2_ITERATOR *it;
01217 
01218   it=GWEN_StringList2_First(sl);
01219   if (it) {
01220     const char *t;
01221 
01222     t=GWEN_StringList2Iterator_Data(it);
01223     assert(t);
01224     while(t) {
01225       const char *p;
01226 
01227       p=strchr(t, ':');
01228       assert(p);
01229       p++;
01230       if (strcasecmp(p, s)==0) {
01231         GWEN_StringList2Iterator_free(it);
01232         return t;
01233       }
01234       t=GWEN_StringList2Iterator_Next(it);
01235     } /* while */
01236     GWEN_StringList2Iterator_free(it);
01237   }
01238   return 0;
01239 }
01240 
01241 
01242 
01243 const char *GWEN_XML_FindNameSpace(GWEN_STRINGLIST2 *sl,
01244                                    const char *prefix,
01245                                    const char *name){
01246   GWEN_BUFFER *nbuf;
01247   GWEN_STRINGLIST2_ITERATOR *it;
01248 
01249   nbuf=GWEN_Buffer_new(0, 32, 0, 1);
01250   if (prefix)
01251     GWEN_Buffer_AppendString(nbuf, prefix);
01252   GWEN_Buffer_AppendByte(nbuf, ':');
01253   GWEN_Buffer_AppendString(nbuf, name);
01254 
01255   it=GWEN_StringList2_First(sl);
01256   if (it) {
01257     const char *t;
01258 
01259     t=GWEN_StringList2Iterator_Data(it);
01260     assert(t);
01261     while(t) {
01262       const char *p;
01263 
01264       p=strchr(t, ':');
01265       assert(p);
01266       p++;
01267       if (strcasecmp(p, GWEN_Buffer_GetStart(nbuf))==0) {
01268         GWEN_StringList2Iterator_free(it);
01269         GWEN_Buffer_free(nbuf);
01270         return t;
01271       }
01272       t=GWEN_StringList2Iterator_Next(it);
01273     } /* while */
01274     GWEN_StringList2Iterator_free(it);
01275   }
01276 
01277   GWEN_Buffer_free(nbuf);
01278   return 0;
01279 }
01280 
01281 
01282 
01283 int GWEN_XMLNode__CheckNameSpaceDecls1(GWEN_XMLNODE *n,
01284                                        GWEN_STRINGLIST2 *sl,
01285                                        const char *currentNameSpace) {
01286   GWEN_XMLPROPERTY *pr;
01287   GWEN_XMLNODE *nn;
01288   char *localNameSpace;
01289 
01290   localNameSpace=0;
01291 
01292   /* remove all unnecessary namespace declarations from this node */
01293   pr=n->properties;
01294   while(pr) {
01295     GWEN_XMLPROPERTY *prNext;
01296 
01297     prNext=pr->next;
01298     if (strcasecmp(pr->name, "xmlns")==0) {
01299       /* default namespace changed ? */
01300       if (localNameSpace) {
01301         if (strcasecmp(pr->value, localNameSpace)==0) {
01302           /* already mentioned name space, remove duplicate property */
01303           GWEN_XMLProperty_del(pr, &n->properties);
01304           GWEN_XMLProperty_free(pr);
01305         }
01306         else {
01307           /* current namespace changed */
01308           GWEN_Memory_dealloc(localNameSpace);
01309           localNameSpace=GWEN_Memory_strdup(pr->value);
01310         }
01311       }
01312       else if (currentNameSpace) {
01313         if (strcasecmp(pr->value, currentNameSpace)==0) {
01314           /* already active name space, remove property */
01315           GWEN_XMLProperty_del(pr, &n->properties);
01316           GWEN_XMLProperty_free(pr);
01317         }
01318         else {
01319           /* current namespace changed */
01320           GWEN_Memory_dealloc(localNameSpace);
01321           localNameSpace=GWEN_Memory_strdup(pr->value);
01322         }
01323       }
01324       else {
01325         /* set current namespace */
01326         GWEN_Memory_dealloc(localNameSpace);
01327         localNameSpace=GWEN_Memory_strdup(pr->value);
01328       }
01329     }
01330     else if (strncasecmp(pr->name, "xmlns:", 6)==0) {
01331       const char *prefix;
01332       const char *x;
01333 
01334       prefix=strchr(pr->name, ':');
01335       prefix++;
01336 
01337       /* check for redefinition */
01338       x=GWEN_XML_FindNameSpaceByName(sl, prefix);
01339       if (x) {
01340         const char *p;
01341 
01342         /* prefix already in use, check whether it is the same namespace */
01343         p=strchr(x, ':');
01344         assert(p);
01345         p++;
01346         if (strcasecmp(p, pr->value)!=0) {
01347           GWEN_BUFFER *xpath;
01348 
01349           /* same prefix, different namespace */
01350           xpath=GWEN_Buffer_new(0, 256, 0, 1);
01351           GWEN_XMLNode_GetXPath(0, n, xpath);
01352           DBG_ERROR(GWEN_LOGDOMAIN,
01353                     "Redefinition of namespace prefix \"%s\" in \"%s\"",
01354                     prefix, GWEN_Buffer_GetStart(xpath));
01355           GWEN_Buffer_free(xpath);
01356           return -1;
01357         } /* if different namespace for same prefix */
01358         else {
01359           /* already in list, remove property here */
01360           GWEN_XMLProperty_del(pr, &n->properties);
01361           GWEN_XMLProperty_free(pr);
01362         }
01363       }
01364       else {
01365         GWEN_XML_AddNameSpace(sl, prefix, pr->value);
01366       }
01367     }
01368     pr=prNext;
01369   } /* while */
01370 
01371   /* do the same on all sub nodes */
01372   nn=GWEN_XMLNode_GetFirstTag(n);
01373   while(nn) {
01374     int rv;
01375 
01376     rv=GWEN_XMLNode__CheckNameSpaceDecls1(nn, sl,
01377                                           localNameSpace?localNameSpace:
01378                                           currentNameSpace);
01379     if (rv) {
01380       GWEN_Memory_dealloc(localNameSpace);
01381       return rv;
01382     }
01383     nn=GWEN_XMLNode_GetNextTag(nn);
01384   }
01385 
01386   GWEN_Memory_dealloc(localNameSpace);
01387   return 0;
01388 }
01389 
01390 
01391 
01392 int GWEN_XMLNode__CheckAndSetNameSpace(GWEN_XMLNODE *n,
01393                                        const char *prefix,
01394                                        const char *nspace) {
01395   GWEN_XMLPROPERTY *pr;
01396   const char *p;
01397   int inUse;
01398 
01399   inUse=0;
01400   /* check current tag for prefix */
01401   if (prefix) {
01402     p=strchr(n->data, ':');
01403     if (p) {
01404       if (strncasecmp(n->data, prefix, p-n->data)==0) {
01405         DBG_DEBUG(GWEN_LOGDOMAIN, "Prefix \"%s\" used in tag \"%s\"",
01406                    prefix, n->data);
01407         inUse=1;
01408       }
01409     }
01410 
01411     if (!inUse) {
01412       /* check all attributes for prefixes */
01413       pr=n->properties;
01414       while(pr) {
01415         p=strchr(pr->name, ':');
01416         if (p) {
01417           if (strncasecmp(pr->name, prefix, p-pr->name)==0) {
01418             DBG_DEBUG(GWEN_LOGDOMAIN,
01419                        "Prefix \"%s\" used in attribute \"%s\" of tag \"%s\"",
01420                        prefix, pr->name, n->data);
01421             inUse=1;
01422             break;
01423           }
01424           else {
01425             DBG_DEBUG(GWEN_LOGDOMAIN,
01426                        "Prefix \"%s\" not used in attribute \"%s\" of tag \"%s\"",
01427                        prefix, pr->name, n->data);
01428           }
01429         }
01430         pr=pr->next;
01431       } /* while */
01432     }
01433   } /* if prefix */
01434   else {
01435     /* no prefix, check whether the current element hasn't any */
01436     p=strchr(n->data, ':');
01437     if (!p) {
01438       /* current tag has no prefix, check whether we have a namespace
01439        * declaration here */
01440       if (GWEN_XMLNode_GetProperty(n, "xmlns", 0)==0) {
01441         /* no, so the current namespace from above is used */
01442         DBG_DEBUG(GWEN_LOGDOMAIN,
01443                    "No prefix, current namespace is used");
01444         inUse=1;
01445       }
01446     }
01447   } /* if no prefix */
01448 
01449   if (inUse) {
01450     GWEN_BUFFER *nbuf;
01451 
01452     nbuf=GWEN_Buffer_new(0, 32, 0, 1);
01453     GWEN_Buffer_AppendString(nbuf, "xmlns");
01454     if (prefix) {
01455       GWEN_Buffer_AppendByte(nbuf, ':');
01456       GWEN_Buffer_AppendString(nbuf, prefix);
01457     }
01458     GWEN_XMLNode__SetProperty(n, GWEN_Buffer_GetStart(nbuf), nspace, 1);
01459     GWEN_Buffer_free(nbuf);
01460     return 1;
01461   }
01462 
01463   return 0;
01464 }
01465 
01466 
01467 
01468 int GWEN_XMLNode__SetNameSpaces(GWEN_XMLNODE *n,
01469                                 const char *prefix,
01470                                 const char *nspace) {
01471   GWEN_XMLNODE *nn;
01472   int rv;
01473 
01474   rv=GWEN_XMLNode__CheckAndSetNameSpace(n, prefix, nspace);
01475   if (rv)
01476     return rv;
01477 
01478   nn=GWEN_XMLNode_GetFirstTag(n);
01479   while(nn) {
01480     rv=GWEN_XMLNode__CheckAndSetNameSpace(nn, prefix, nspace);
01481     if (rv==-1)
01482       return rv;
01483     else if (rv==0) {
01484       /* check children */
01485       rv=GWEN_XMLNode__SetNameSpaces(nn, prefix, nspace);
01486       if (rv)
01487         return rv;
01488     }
01489 
01490     nn=GWEN_XMLNode_GetNextTag(nn);
01491   }
01492 
01493   return 0;
01494 }
01495 
01496 
01497 
01498 int GWEN_XMLNode__CheckNameSpaceDecls3(GWEN_XMLNODE *n) {
01499   GWEN_XMLPROPERTY *pr;
01500   GWEN_XMLNODE *nn;
01501   int rv;
01502 
01503   /* move all namespace declarations from this node to the nodes
01504    * of first use */
01505   pr=n->properties;
01506   while(pr) {
01507     GWEN_XMLPROPERTY *prNext;
01508 
01509     prNext=pr->next;
01510     if (strcasecmp(pr->name, "xmlns")==0 ||
01511         strncasecmp(pr->name, "xmlns:", 6)==0) {
01512       const char *prefix;
01513 
01514       prefix=strchr(pr->name, ':');
01515       if (prefix)
01516         prefix++;
01517 
01518       GWEN_XMLProperty_del(pr, &n->properties);
01519       rv=GWEN_XMLNode__SetNameSpaces(n, prefix, pr->value);
01520       DBG_DEBUG(GWEN_LOGDOMAIN, "Removing property \"%s\"",
01521                  pr->name);
01522       GWEN_XMLProperty_free(pr);
01523       if (rv==-1)
01524         return rv;
01525     }
01526     pr=prNext;
01527   } /* while */
01528 
01529   /* do the same on all sub nodes */
01530   nn=GWEN_XMLNode_GetFirstTag(n);
01531   while(nn) {
01532     rv=GWEN_XMLNode__CheckNameSpaceDecls3(nn);
01533     if (rv) {
01534       return rv;
01535     }
01536     nn=GWEN_XMLNode_GetNextTag(nn);
01537   }
01538 
01539   return 0;
01540 }
01541 
01542 
01543 
01544 
01545 int GWEN_XMLNode_NormalizeNameSpaces(GWEN_XMLNODE *n) {
01546   const char *ns;
01547   int rv;
01548   GWEN_STRINGLIST2 *sl;
01549 
01550   ns=GWEN_XMLNode_GetProperty(n, "xmlns", 0);
01551   sl=GWEN_StringList2_new();
01552   rv=GWEN_XMLNode__CheckNameSpaceDecls1(n, sl, ns);
01553   GWEN_StringList2_free(sl);
01554   if (rv) {
01555     DBG_INFO(GWEN_LOGDOMAIN, "here");
01556     return rv;
01557   }
01558 
01559   //rv=GWEN_XMLNode__CheckNameSpaceDecls2(n, ns);
01560   rv=GWEN_XMLNode__CheckNameSpaceDecls3(n);
01561   if (rv==-1)
01562     return rv;
01563   return 0;
01564 }
01565 
01566 
01567 
01568 int GWEN_XMLNode_StripNamespaces(GWEN_XMLNODE *n) {
01569   if (n && n->type==GWEN_XMLNodeTypeTag && n->data) {
01570     GWEN_XMLNODE *nn;
01571 
01572     if (n->nameSpace==0) {
01573       char *p;
01574 
01575       p=strchr(n->data, ':');
01576       if (p) {
01577         int len=p-n->data;
01578         char *s;
01579 
01580         n->nameSpace=(char*)GWEN_Memory_malloc(len);
01581         assert(n->nameSpace);
01582         memmove(n->nameSpace, n->data, len);
01583         n->nameSpace[len-1]=0;
01584         s=GWEN_Memory_strdup(p+1);
01585         free(n->data);
01586         n->data=s;
01587       }
01588     }
01589 
01590     nn=GWEN_XMLNode_List_First(n->children);
01591     while(nn) {
01592       int rv;
01593 
01594       rv=GWEN_XMLNode_StripNamespaces(nn);
01595       if (rv<0) {
01596         DBG_DEBUG(GWEN_LOGDOMAIN, "here (%d)", rv);
01597         return rv;
01598       }
01599       nn=GWEN_XMLNode_List_Next(nn);
01600     }
01601   }
01602 
01603   return 0;
01604 }
01605 
01606 
01607 
01608 
01609 
01610 
01611 
01612 
01613 
01614 GWEN_XMLNODE_PATH *GWEN_XMLNode_Path_new(){
01615   GWEN_XMLNODE_PATH *p;
01616 
01617   GWEN_NEW_OBJECT(GWEN_XMLNODE_PATH, p);
01618   return p;
01619 }
01620 
01621 
01622 
01623 GWEN_XMLNODE_PATH *GWEN_XMLNode_Path_dup(const GWEN_XMLNODE_PATH *np){
01624   GWEN_XMLNODE_PATH *p;
01625   unsigned int i;
01626 
01627   GWEN_NEW_OBJECT(GWEN_XMLNODE_PATH, p);
01628   p->pos=np->pos;
01629   for (i=0; i<np->pos; i++) {
01630     p->nodes[i]=np->nodes[i];
01631   }
01632   return p;
01633 }
01634 
01635 
01636 
01637 void GWEN_XMLNode_Path_free(GWEN_XMLNODE_PATH *np){
01638   GWEN_FREE_OBJECT(np);
01639 }
01640 
01641 
01642 
01643 int GWEN_XMLNode_Path_Dive(GWEN_XMLNODE_PATH *np,
01644                            GWEN_XMLNODE *n){
01645   unsigned int i;
01646 
01647   if (np->pos>=GWEN_XML_MAX_DEPTH) {
01648     DBG_ERROR(GWEN_LOGDOMAIN, "Path too deep");
01649     return 1;
01650   }
01651 
01652   /* check for double entries */
01653   for (i=0; i<np->pos; i++) {
01654     assert(np->nodes[i]!=n);
01655   }
01656   np->nodes[np->pos++]=n;
01657   DBG_DEBUG(GWEN_LOGDOMAIN, "Dived to %d", np->pos);
01658   return 0;
01659 }
01660 
01661 
01662 
01663 GWEN_XMLNODE *GWEN_XMLNode_Path_Surface(GWEN_XMLNODE_PATH *np){
01664   if (np->pos==0) {
01665     DBG_DEBUG(GWEN_LOGDOMAIN, "Root reached");
01666     return 0;
01667   }
01668   DBG_DEBUG(GWEN_LOGDOMAIN, "Surfaced to %d", np->pos-1);
01669   return np->nodes[--np->pos];
01670 }
01671 
01672 
01673 
01674 void GWEN_XMLNode_Path_Dump(GWEN_XMLNODE_PATH *np){
01675   unsigned int i;
01676 
01677   if (np->pos==0) {
01678     DBG_NOTICE(GWEN_LOGDOMAIN, "Empty path");
01679   }
01680   for (i=0; i<np->pos; i++) {
01681     DBG_NOTICE(GWEN_LOGDOMAIN, "Path entry %d:", i);
01682     GWEN_XMLNode_Dump(np->nodes[i], stderr, 1);
01683   }
01684 }
01685 
01686 
01687 
01688 
01689 
01690 
01691 
01692 
01693 
01694 
01695 
01696 GWEN_XMLNODE_NAMESPACE *GWEN_XMLNode_NameSpace_new(const char *name,
01697                                                    const char *url) {
01698   GWEN_XMLNODE_NAMESPACE *ns;
01699 
01700   GWEN_NEW_OBJECT(GWEN_XMLNODE_NAMESPACE, ns);
01701   GWEN_LIST_INIT(GWEN_XMLNODE_NAMESPACE, ns);
01702 
01703   if (name)
01704     ns->name=GWEN_Memory_strdup(name);
01705   if (url)
01706     ns->url=GWEN_Memory_strdup(url);
01707 
01708   return ns;
01709 }
01710 
01711 
01712 
01713 void GWEN_XMLNode_NameSpace_free(GWEN_XMLNODE_NAMESPACE *ns) {
01714   if (ns) {
01715     GWEN_LIST_FINI(GWEN_XMLNODE_NAMESPACE, ns);
01716     free(ns->url);
01717     free(ns->name);
01718     GWEN_FREE_OBJECT(ns);
01719   }
01720 }
01721 
01722 
01723 
01724 GWEN_XMLNODE_NAMESPACE *GWEN_XMLNode_NameSpace_dup(const GWEN_XMLNODE_NAMESPACE *ns) {
01725   GWEN_XMLNODE_NAMESPACE *nns;
01726 
01727   assert(ns);
01728   nns=GWEN_XMLNode_NameSpace_new(ns->name, ns->url);
01729   return nns;
01730 }
01731 
01732 
01733 
01734 const char *GWEN_XMLNode_NameSpace_GetName(const GWEN_XMLNODE_NAMESPACE *ns) {
01735   assert(ns);
01736   return ns->name;
01737 }
01738 
01739 
01740 
01741 const char *GWEN_XMLNode_NameSpace_GetUrl(const GWEN_XMLNODE_NAMESPACE *ns) {
01742   assert(ns);
01743   return ns->url;
01744 }
01745 
01746 
01747 
01748 
01749 
01750 
01751 #include "xmlrw.c"
01752 #include "xmlglobalize.c"
01753 
01754 
01755 
Generated on Mon Jul 5 22:52:48 2010 for gwenhywfar by  doxygen 1.6.3