xml.c

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