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