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