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

Generated on Wed Jul 9 13:12:28 2008 for gwenhywfar by  doxygen 1.5.6