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 #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 }
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 }
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
00183 nn=GWEN_XMLNode_new(n->type, n->data);
00184 if (n->nameSpace)
00185 nn->nameSpace=strdup(n->nameSpace);
00186
00187
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 }
00196
00197
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 }
00204
00205
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 }
00212
00213
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 }
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 }
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 }
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 }
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
00533 while(tp) {
00534
00535 assert(tp->name);
00536 if (strcasecmp(tp->name, sp->name)==0) {
00537
00538 if (overwrite) {
00539
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 }
00549
00550 if (!tp) {
00551
00552 np=GWEN_XMLProperty_dup(sp);
00553 GWEN_XMLProperty_add(np, &(tn->properties));
00554 }
00555
00556 sp=sp->next;
00557 }
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 }
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 }
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
00643 if (!pvalue)
00644 return (GWEN_XMLNODE*)n;
00645 }
00646 }
00647 else
00648 return (GWEN_XMLNODE*)n;
00649 }
00650 n=GWEN_XMLNode_GetNextTag(n);
00651 }
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 }
00741 se=GWEN_StringListEntry_Next(se);
00742 }
00743 }
00744
00745
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
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
00910 GWEN_Buffer_AppendBuffer(nbuf, lbuf);
00911 }
00912 DBG_ERROR(GWEN_LOGDOMAIN, "Path so far: %s", GWEN_Buffer_GetStart(lbuf));
00913
00914
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
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
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
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
01002 if (flags & GWEN_PATH_FLAGS_VARIABLE) {
01003
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
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
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
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 }
01049 else {
01050
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 }
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 }
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 }
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
01295 pr=n->properties;
01296 while(pr) {
01297 GWEN_XMLPROPERTY *prNext;
01298
01299 prNext=pr->next;
01300 if (strcasecmp(pr->name, "xmlns")==0) {
01301
01302 if (localNameSpace) {
01303 if (strcasecmp(pr->value, localNameSpace)==0) {
01304
01305 GWEN_XMLProperty_del(pr, &n->properties);
01306 GWEN_XMLProperty_free(pr);
01307 }
01308 else {
01309
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
01317 GWEN_XMLProperty_del(pr, &n->properties);
01318 GWEN_XMLProperty_free(pr);
01319 }
01320 else {
01321
01322 GWEN_Memory_dealloc(localNameSpace);
01323 localNameSpace=GWEN_Memory_strdup(pr->value);
01324 }
01325 }
01326 else {
01327
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
01340 x=GWEN_XML_FindNameSpaceByName(sl, prefix);
01341 if (x) {
01342 const char *p;
01343
01344
01345 p=strchr(x, ':');
01346 assert(p);
01347 p++;
01348 if (strcasecmp(p, pr->value)!=0) {
01349 GWEN_BUFFER *xpath;
01350
01351
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 }
01360 else {
01361
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 }
01372
01373
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
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
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 }
01434 }
01435 }
01436 else {
01437
01438 p=strchr(n->data, ':');
01439 if (!p) {
01440
01441
01442 if (GWEN_XMLNode_GetProperty(n, "xmlns", 0)==0) {
01443
01444 DBG_DEBUG(GWEN_LOGDOMAIN,
01445 "No prefix, current namespace is used");
01446 inUse=1;
01447 }
01448 }
01449 }
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
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
01506
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 }
01530
01531
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
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
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