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