mcabber/libjabber/xmlnode.c
changeset 25 bf3d6e241714
child 417 c3ae9251c197
equal deleted inserted replaced
24:e88b15cbf2de 25:bf3d6e241714
       
     1 /*
       
     2  *  This program is free software; you can redistribute it and/or modify
       
     3  *  it under the terms of the GNU General Public License as published by
       
     4  *  the Free Software Foundation; either version 2 of the License, or
       
     5  *  (at your option) any later version.
       
     6  *
       
     7  *  This program is distributed in the hope that it will be useful,
       
     8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
     9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    10  *  GNU General Public License for more details.
       
    11  *
       
    12  *  You should have received a copy of the GNU General Public License
       
    13  *  along with this program; if not, write to the Free Software
       
    14  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
       
    15  *
       
    16  *  Jabber
       
    17  *  Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
       
    18  */
       
    19 
       
    20 #include "libxode.h"
       
    21 
       
    22 /* Internal routines */
       
    23 xmlnode _xmlnode_new(pool p, const char* name, unsigned int type)
       
    24 {
       
    25     xmlnode result = NULL;
       
    26     if (type > NTYPE_LAST)
       
    27         return NULL;
       
    28 
       
    29     if (type != NTYPE_CDATA && name == NULL)
       
    30         return NULL;
       
    31 
       
    32     if (p == NULL)
       
    33     {
       
    34         p = pool_heap(1*1024);
       
    35     }
       
    36 
       
    37     /* Allocate & zero memory */
       
    38     result = (xmlnode)pmalloc(p, sizeof(_xmlnode));
       
    39     memset(result, '\0', sizeof(_xmlnode));
       
    40 
       
    41     /* Initialize fields */
       
    42     if (type != NTYPE_CDATA)
       
    43         result->name = pstrdup(p,name);
       
    44     result->type = type;
       
    45     result->p = p;
       
    46     return result;
       
    47 }
       
    48 
       
    49 static xmlnode _xmlnode_append_sibling(xmlnode lastsibling, const char* name, unsigned int type)
       
    50 {
       
    51     xmlnode result;
       
    52 
       
    53     result = _xmlnode_new(xmlnode_pool(lastsibling), name, type);
       
    54     if (result != NULL)
       
    55     {
       
    56         /* Setup sibling pointers */
       
    57         result->prev = lastsibling;
       
    58         lastsibling->next = result;
       
    59     }
       
    60     return result;
       
    61 }
       
    62 
       
    63 static xmlnode _xmlnode_insert(xmlnode parent, const char* name, unsigned int type)
       
    64 {
       
    65     xmlnode result;
       
    66 
       
    67     if(parent == NULL || name == NULL) return NULL;
       
    68 
       
    69     /* If parent->firstchild is NULL, simply create a new node for the first child */
       
    70     if (parent->firstchild == NULL)
       
    71     {
       
    72         result = _xmlnode_new(parent->p, name, type);
       
    73         parent->firstchild = result;
       
    74     }
       
    75     /* Otherwise, append this to the lastchild */
       
    76     else
       
    77     {
       
    78         result= _xmlnode_append_sibling(parent->lastchild, name, type);
       
    79     }
       
    80     result->parent = parent;
       
    81     parent->lastchild = result;
       
    82     return result;
       
    83 
       
    84 }
       
    85 
       
    86 static xmlnode _xmlnode_search(xmlnode firstsibling, const char* name, unsigned int type)
       
    87 {
       
    88     xmlnode current;
       
    89 
       
    90     /* Walk the sibling list, looking for a NTYPE_TAG xmlnode with
       
    91     the specified name */
       
    92     current = firstsibling;
       
    93     while (current != NULL)
       
    94     {
       
    95         if ((current->type == type) && (j_strcmp(current->name, name) == 0))
       
    96             return current;
       
    97         else
       
    98             current = current->next;
       
    99     }
       
   100     return NULL;
       
   101 }
       
   102 
       
   103 static char* _xmlnode_merge(pool p, char* dest, unsigned int destsize, const char* src, unsigned int srcsize)
       
   104 {
       
   105     char* result;
       
   106     result = (char*)pmalloc(p, destsize + srcsize + 1);
       
   107     memcpy(result, dest, destsize);
       
   108     memcpy(result+destsize, src, srcsize);
       
   109     result[destsize + srcsize] = '\0';
       
   110 
       
   111     /* WARNING: major ugly hack: since we're throwing the old data away, let's jump in the pool and subtract it from the size, this is for xmlstream's big-node checking */
       
   112     p->size -= destsize;
       
   113 
       
   114     return result;
       
   115 }
       
   116 
       
   117 static void _xmlnode_hide_sibling(xmlnode child)
       
   118 {
       
   119     if(child == NULL)
       
   120         return;
       
   121 
       
   122     if(child->prev != NULL)
       
   123         child->prev->next = child->next;
       
   124     if(child->next != NULL)
       
   125         child->next->prev = child->prev;
       
   126 }
       
   127 
       
   128 void _xmlnode_tag2str(spool s, xmlnode node, int flag)
       
   129 {
       
   130     xmlnode tmp;
       
   131 
       
   132     if(flag==0 || flag==1)
       
   133     {
       
   134 	    spooler(s,"<",xmlnode_get_name(node),s);
       
   135 	    tmp = xmlnode_get_firstattrib(node);
       
   136 	    while(tmp) {
       
   137 	        spooler(s," ",xmlnode_get_name(tmp),"='",strescape(xmlnode_pool(node),xmlnode_get_data(tmp)),"'",s);
       
   138 	        tmp = xmlnode_get_nextsibling(tmp);
       
   139 	    }
       
   140 	    if(flag==0)
       
   141 	        spool_add(s,"/>");
       
   142 	    else
       
   143 	        spool_add(s,">");
       
   144     }
       
   145     else
       
   146     {
       
   147 	    spooler(s,"</",xmlnode_get_name(node),">",s);
       
   148     }
       
   149 }
       
   150 
       
   151 spool _xmlnode2spool(xmlnode node)
       
   152 {
       
   153     spool s;
       
   154     int level=0,dir=0;
       
   155     xmlnode tmp;
       
   156 
       
   157     if(!node || xmlnode_get_type(node)!=NTYPE_TAG)
       
   158 	return NULL;
       
   159 
       
   160     s = spool_new(xmlnode_pool(node));
       
   161     if(!s) return(NULL);
       
   162 
       
   163     while(1)
       
   164     {
       
   165         if(dir==0)
       
   166         {
       
   167     	    if(xmlnode_get_type(node) == NTYPE_TAG)
       
   168             {
       
   169 		        if(xmlnode_has_children(node))
       
   170                 {
       
   171 		            _xmlnode_tag2str(s,node,1);
       
   172         		    node = xmlnode_get_firstchild(node);
       
   173 		            level++;
       
   174 		            continue;
       
   175         		}
       
   176                 else
       
   177                 {
       
   178 		            _xmlnode_tag2str(s,node,0);
       
   179 		        }
       
   180 	        }
       
   181             else
       
   182             {
       
   183 		        spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node)));
       
   184 	        }
       
   185 	    }
       
   186 
       
   187     	tmp = xmlnode_get_nextsibling(node);
       
   188 	    if(!tmp)
       
   189         {
       
   190 	        node = xmlnode_get_parent(node);
       
   191 	        level--;
       
   192 	        if(level>=0) _xmlnode_tag2str(s,node,2);
       
   193 	        if(level<1) break;
       
   194 	        dir = 1;
       
   195 	    }
       
   196         else
       
   197         {
       
   198 	        node = tmp;
       
   199 	        dir = 0;
       
   200 	    }
       
   201     }
       
   202 
       
   203     return s;
       
   204 }
       
   205 
       
   206 
       
   207 /* External routines */
       
   208 
       
   209 
       
   210 /*
       
   211  *  xmlnode_new_tag -- create a tag node
       
   212  *  Automatically creates a memory pool for the node.
       
   213  *
       
   214  *  parameters
       
   215  *      name -- name of the tag
       
   216  *
       
   217  *  returns
       
   218  *      a pointer to the tag node
       
   219  *      or NULL if it was unsuccessfull
       
   220  */
       
   221 xmlnode xmlnode_new_tag(const char* name)
       
   222 {
       
   223     return _xmlnode_new(NULL, name, NTYPE_TAG);
       
   224 }
       
   225 
       
   226 
       
   227 /*
       
   228  *  xmlnode_new_tag_pool -- create a tag node within given pool
       
   229  *
       
   230  *  parameters
       
   231  *      p -- previously created memory pool
       
   232  *      name -- name of the tag
       
   233  *
       
   234  *  returns
       
   235  *      a pointer to the tag node
       
   236  *      or NULL if it was unsuccessfull
       
   237  */
       
   238 xmlnode xmlnode_new_tag_pool(pool p, const char* name)
       
   239 {
       
   240     return _xmlnode_new(p, name, NTYPE_TAG);
       
   241 }
       
   242 
       
   243 
       
   244 /*
       
   245  *  xmlnode_insert_tag -- append a child tag to a tag
       
   246  *
       
   247  *  parameters
       
   248  *      parent -- pointer to the parent tag
       
   249  *      name -- name of the child tag
       
   250  *
       
   251  *  returns
       
   252  *      a pointer to the child tag node
       
   253  *      or NULL if it was unsuccessfull
       
   254  */
       
   255 xmlnode xmlnode_insert_tag(xmlnode parent, const char* name)
       
   256 {
       
   257     return _xmlnode_insert(parent, name, NTYPE_TAG);
       
   258 }
       
   259 
       
   260 
       
   261 /*
       
   262  *  xmlnode_insert_cdata -- append character data to a tag
       
   263  *  If last child of the parent is CDATA, merges CDATA nodes. Otherwise
       
   264  *  creates a CDATA node, and appends it to the parent's child list.
       
   265  *
       
   266  *  parameters
       
   267  *      parent -- parent tag
       
   268  *      CDATA -- character data
       
   269  *      size -- size of CDATA
       
   270  *              or -1 for null-terminated CDATA strings
       
   271  *
       
   272  *  returns
       
   273  *      a pointer to the child CDATA node
       
   274  *      or NULL if it was unsuccessfull
       
   275  */
       
   276 xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size)
       
   277 {
       
   278     xmlnode result;
       
   279 
       
   280     if(CDATA == NULL || parent == NULL)
       
   281         return NULL;
       
   282 
       
   283     if(size == -1)
       
   284         size = strlen(CDATA);
       
   285 
       
   286     if ((parent->lastchild != NULL) && (parent->lastchild->type == NTYPE_CDATA))
       
   287     {
       
   288         result = parent->lastchild;
       
   289         result->data = _xmlnode_merge(result->p, result->data, result->data_sz, CDATA, size);
       
   290         result->data_sz = result->data_sz + size;
       
   291     }
       
   292     else
       
   293     {
       
   294         result = _xmlnode_insert(parent, "", NTYPE_CDATA);
       
   295         if (result != NULL)
       
   296         {
       
   297             result->data = (char*)pmalloc(result->p, size + 1);
       
   298             memcpy(result->data, CDATA, size);
       
   299             result->data[size] = '\0';
       
   300             result->data_sz = size;
       
   301         }
       
   302     }
       
   303 
       
   304     return result;
       
   305 }
       
   306 
       
   307 
       
   308 /*
       
   309  *  xmlnode_get_tag -- find given tag in an xmlnode tree
       
   310  *
       
   311  *  parameters
       
   312  *      parent -- pointer to the parent tag
       
   313  *      name -- "name" for the child tag of that name
       
   314  *              "name/name" for a sub child (recurses)
       
   315  *              "?attrib" to match the first tag with that attrib defined
       
   316  *              "?attrib=value" to match the first tag with that attrib and value
       
   317  *              or any combination: "name/name/?attrib", etc
       
   318  *
       
   319  *  results
       
   320  *      a pointer to the tag matching search criteria
       
   321  *      or NULL if search was unsuccessfull
       
   322  */
       
   323 xmlnode xmlnode_get_tag(xmlnode parent, const char* name)
       
   324 {
       
   325     char *str, *slash, *qmark, *equals;
       
   326     xmlnode step, ret;
       
   327 
       
   328     if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL;
       
   329 
       
   330     if(strstr(name, "/") == NULL && strstr(name,"?") == NULL)
       
   331         return _xmlnode_search(parent->firstchild, name, NTYPE_TAG);
       
   332 
       
   333     /* jer's note: why can't I modify the name directly, why do I have to strdup it?  damn c grrr! */
       
   334     str = strdup(name);
       
   335     slash = strstr(str, "/");
       
   336     qmark = strstr(str, "?");
       
   337     equals = strstr(str, "=");
       
   338 
       
   339     if(qmark != NULL && (slash == NULL || qmark < slash))
       
   340     { /* of type ?attrib */
       
   341 
       
   342         *qmark = '\0';
       
   343         qmark++;
       
   344         if(equals != NULL)
       
   345         {
       
   346             *equals = '\0';
       
   347             equals++;
       
   348         }
       
   349 
       
   350         for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step))
       
   351         {
       
   352             if(xmlnode_get_type(step) != NTYPE_TAG)
       
   353                 continue;
       
   354 
       
   355             if(*str != '\0')
       
   356                 if(j_strcmp(xmlnode_get_name(step),str) != 0)
       
   357                     continue;
       
   358 
       
   359             if(xmlnode_get_attrib(step,qmark) == NULL)
       
   360                 continue;
       
   361 
       
   362             if(equals != NULL && j_strcmp(xmlnode_get_attrib(step,qmark),equals) != 0)
       
   363                 continue;
       
   364 
       
   365             break;
       
   366         }
       
   367 
       
   368         free(str);
       
   369         return step;
       
   370     }
       
   371 
       
   372 
       
   373     *slash = '\0';
       
   374     ++slash;
       
   375 
       
   376     for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step))
       
   377     {
       
   378         if(xmlnode_get_type(step) != NTYPE_TAG) continue;
       
   379 
       
   380         if(j_strcmp(xmlnode_get_name(step),str) != 0)
       
   381             continue;
       
   382 
       
   383         ret = xmlnode_get_tag(step, slash);
       
   384         if(ret != NULL)
       
   385         {
       
   386             free(str);
       
   387             return ret;
       
   388         }
       
   389     }
       
   390 
       
   391     free(str);
       
   392     return NULL;
       
   393 }
       
   394 
       
   395 
       
   396 /* return the cdata from any tag */
       
   397 char *xmlnode_get_tag_data(xmlnode parent, const char *name)
       
   398 {
       
   399     xmlnode tag;
       
   400 
       
   401     tag = xmlnode_get_tag(parent, name);
       
   402     if(tag == NULL) return NULL;
       
   403 
       
   404     return xmlnode_get_data(tag);
       
   405 }
       
   406 
       
   407 
       
   408 void xmlnode_put_attrib(xmlnode owner, const char* name, const char* value)
       
   409 {
       
   410     xmlnode attrib;
       
   411 
       
   412     if(owner == NULL || name == NULL || value == NULL) return;
       
   413 
       
   414     /* If there are no existing attributs, allocate a new one to start
       
   415     the list */
       
   416     if (owner->firstattrib == NULL)
       
   417     {
       
   418         attrib = _xmlnode_new(owner->p, name, NTYPE_ATTRIB);
       
   419         owner->firstattrib = attrib;
       
   420         owner->lastattrib  = attrib;
       
   421     }
       
   422     else
       
   423     {
       
   424         attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB);
       
   425         if(attrib == NULL)
       
   426         {
       
   427             attrib = _xmlnode_append_sibling(owner->lastattrib, name, NTYPE_ATTRIB);
       
   428             owner->lastattrib = attrib;
       
   429         }
       
   430     }
       
   431     /* Update the value of the attribute */
       
   432     attrib->data_sz = strlen(value);
       
   433     attrib->data    = pstrdup(owner->p, value);
       
   434 
       
   435 }
       
   436 
       
   437 char* xmlnode_get_attrib(xmlnode owner, const char* name)
       
   438 {
       
   439     xmlnode attrib;
       
   440 
       
   441     if (owner != NULL && owner->firstattrib != NULL)
       
   442     {
       
   443         attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB);
       
   444         if (attrib != NULL)
       
   445             return (char*)attrib->data;
       
   446     }
       
   447     return NULL;
       
   448 }
       
   449 
       
   450 void xmlnode_put_vattrib(xmlnode owner, const char* name, void *value)
       
   451 {
       
   452     xmlnode attrib;
       
   453 
       
   454     if (owner != NULL)
       
   455     {
       
   456         attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB);
       
   457         if (attrib == NULL)
       
   458         {
       
   459             xmlnode_put_attrib(owner, name, "");
       
   460             attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB);
       
   461         }
       
   462         if (attrib != NULL)
       
   463             attrib->firstchild = (xmlnode)value;
       
   464     }
       
   465 }
       
   466 
       
   467 void* xmlnode_get_vattrib(xmlnode owner, const char* name)
       
   468 {
       
   469     xmlnode attrib;
       
   470 
       
   471     if (owner != NULL && owner->firstattrib != NULL)
       
   472     {
       
   473         attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB);
       
   474         if (attrib != NULL)
       
   475             return (void*)attrib->firstchild;
       
   476     }
       
   477     return NULL;
       
   478 }
       
   479 
       
   480 xmlnode xmlnode_get_firstattrib(xmlnode parent)
       
   481 {
       
   482     if (parent != NULL)
       
   483         return parent->firstattrib;
       
   484     return NULL;
       
   485 }
       
   486 
       
   487 xmlnode xmlnode_get_firstchild(xmlnode parent)
       
   488 {
       
   489     if (parent != NULL)
       
   490         return parent->firstchild;
       
   491     return NULL;
       
   492 }
       
   493 
       
   494 xmlnode xmlnode_get_lastchild(xmlnode parent)
       
   495 {
       
   496     if (parent != NULL)
       
   497         return parent->lastchild;
       
   498     return NULL;
       
   499 }
       
   500 
       
   501 xmlnode xmlnode_get_nextsibling(xmlnode sibling)
       
   502 {
       
   503     if (sibling != NULL)
       
   504         return sibling->next;
       
   505     return NULL;
       
   506 }
       
   507 
       
   508 xmlnode xmlnode_get_prevsibling(xmlnode sibling)
       
   509 {
       
   510     if (sibling != NULL)
       
   511         return sibling->prev;
       
   512     return NULL;
       
   513 }
       
   514 
       
   515 xmlnode xmlnode_get_parent(xmlnode node)
       
   516 {
       
   517     if (node != NULL)
       
   518         return node->parent;
       
   519     return NULL;
       
   520 }
       
   521 
       
   522 char* xmlnode_get_name(xmlnode node)
       
   523 {
       
   524     if (node != NULL)
       
   525         return node->name;
       
   526     return NULL;
       
   527 }
       
   528 
       
   529 char* xmlnode_get_data(xmlnode node)
       
   530 {
       
   531     xmlnode cur;
       
   532 
       
   533     if(node == NULL) return NULL;
       
   534 
       
   535     if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA */
       
   536     {
       
   537         for(cur = xmlnode_get_firstchild(node); cur != NULL; cur = xmlnode_get_nextsibling(cur))
       
   538             if(xmlnode_get_type(cur) == NTYPE_CDATA)
       
   539                 return cur->data;
       
   540     }else{
       
   541         return node->data;
       
   542     }
       
   543     return NULL;
       
   544 }
       
   545 
       
   546 int xmlnode_get_datasz(xmlnode node)
       
   547 {
       
   548     if (node != NULL)
       
   549         return node->data_sz;
       
   550     return (int)NULL;
       
   551 }
       
   552 
       
   553 int xmlnode_get_type(xmlnode node)
       
   554 {
       
   555     if (node != NULL)
       
   556         return node->type;
       
   557     return (int)NULL;
       
   558 }
       
   559 
       
   560 int xmlnode_has_children(xmlnode node)
       
   561 {
       
   562     if ((node != NULL) && (node->firstchild != NULL))
       
   563         return 1;
       
   564     return 0;
       
   565 }
       
   566 
       
   567 int xmlnode_has_attribs(xmlnode node)
       
   568 {
       
   569     if ((node != NULL) && (node->firstattrib != NULL))
       
   570         return 1;
       
   571     return 0;
       
   572 }
       
   573 
       
   574 pool xmlnode_pool(xmlnode node)
       
   575 {
       
   576     if (node != NULL)
       
   577         return node->p;
       
   578     return (pool)NULL;
       
   579 }
       
   580 
       
   581 void xmlnode_hide(xmlnode child)
       
   582 {
       
   583     xmlnode parent;
       
   584 
       
   585     if(child == NULL || child->parent == NULL)
       
   586         return;
       
   587 
       
   588     parent = child->parent;
       
   589 
       
   590     /* first fix up at the child level */
       
   591     _xmlnode_hide_sibling(child);
       
   592 
       
   593     /* next fix up at the parent level */
       
   594     if(parent->firstchild == child)
       
   595         parent->firstchild = child->next;
       
   596     if(parent->lastchild == child)
       
   597         parent->lastchild = child->prev;
       
   598 }
       
   599 
       
   600 void xmlnode_hide_attrib(xmlnode parent, const char *name)
       
   601 {
       
   602     xmlnode attrib;
       
   603 
       
   604     if(parent == NULL || parent->firstattrib == NULL || name == NULL)
       
   605         return;
       
   606 
       
   607     attrib = _xmlnode_search(parent->firstattrib, name, NTYPE_ATTRIB);
       
   608     if(attrib == NULL)
       
   609         return;
       
   610 
       
   611     /* first fix up at the child level */
       
   612     _xmlnode_hide_sibling(attrib);
       
   613 
       
   614     /* next fix up at the parent level */
       
   615     if(parent->firstattrib == attrib)
       
   616         parent->firstattrib = attrib->next;
       
   617     if(parent->lastattrib == attrib)
       
   618         parent->lastattrib = attrib->prev;
       
   619 }
       
   620 
       
   621 
       
   622 
       
   623 /*
       
   624  *  xmlnode2str -- convert given xmlnode tree into a string
       
   625  *
       
   626  *  parameters
       
   627  *      node -- pointer to the xmlnode structure
       
   628  *
       
   629  *  results
       
   630  *      a pointer to the created string
       
   631  *      or NULL if it was unsuccessfull
       
   632  */
       
   633 char *xmlnode2str(xmlnode node)
       
   634 {
       
   635      return spool_print(_xmlnode2spool(node));
       
   636 }
       
   637 
       
   638 /*
       
   639  *  xmlnode2tstr -- convert given xmlnode tree into a newline terminated string
       
   640  *
       
   641  *  parameters
       
   642  *      node -- pointer to the xmlnode structure
       
   643  *
       
   644  *  results
       
   645  *      a pointer to the created string
       
   646  *      or NULL if it was unsuccessfull
       
   647  */
       
   648 char*    xmlnode2tstr(xmlnode node)
       
   649 {
       
   650      spool s = _xmlnode2spool(node);
       
   651      if (s != NULL)
       
   652 	  spool_add(s, "\n");
       
   653     return spool_print(s);
       
   654 }
       
   655 
       
   656 
       
   657 /* loop through both a and b comparing everything, attribs, cdata, children, etc */
       
   658 int xmlnode_cmp(xmlnode a, xmlnode b)
       
   659 {
       
   660     int ret = 0;
       
   661 
       
   662     while(1)
       
   663     {
       
   664         if(a == NULL && b == NULL)
       
   665             return 0;
       
   666 
       
   667         if(a == NULL || b == NULL)
       
   668             return -1;
       
   669 
       
   670         if(xmlnode_get_type(a) != xmlnode_get_type(b))
       
   671             return -1;
       
   672 
       
   673         switch(xmlnode_get_type(a))
       
   674         {
       
   675         case NTYPE_ATTRIB:
       
   676             ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b));
       
   677             if(ret != 0)
       
   678                 return -1;
       
   679             ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b));
       
   680             if(ret != 0)
       
   681                 return -1;
       
   682             break;
       
   683         case NTYPE_TAG:
       
   684             ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b));
       
   685             if(ret != 0)
       
   686                 return -1;
       
   687             ret = xmlnode_cmp(xmlnode_get_firstattrib(a), xmlnode_get_firstattrib(b));
       
   688             if(ret != 0)
       
   689                 return -1;
       
   690             ret = xmlnode_cmp(xmlnode_get_firstchild(a), xmlnode_get_firstchild(b));
       
   691             if(ret != 0)
       
   692                 return -1;
       
   693             break;
       
   694         case NTYPE_CDATA:
       
   695             ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b));
       
   696             if(ret != 0)
       
   697                 return -1;
       
   698         }
       
   699         a = xmlnode_get_nextsibling(a);
       
   700         b = xmlnode_get_nextsibling(b);
       
   701     }
       
   702 }
       
   703 
       
   704 
       
   705 xmlnode xmlnode_insert_tag_node(xmlnode parent, xmlnode node)
       
   706 {
       
   707     xmlnode child;
       
   708 
       
   709     child = xmlnode_insert_tag(parent, xmlnode_get_name(node));
       
   710     if (xmlnode_has_attribs(node))
       
   711         xmlnode_insert_node(child, xmlnode_get_firstattrib(node));
       
   712     if (xmlnode_has_children(node))
       
   713         xmlnode_insert_node(child, xmlnode_get_firstchild(node));
       
   714 
       
   715     return child;
       
   716 }
       
   717 
       
   718 /* places copy of node and node's siblings in parent */
       
   719 void xmlnode_insert_node(xmlnode parent, xmlnode node)
       
   720 {
       
   721     if(node == NULL || parent == NULL)
       
   722         return;
       
   723 
       
   724     while(node != NULL)
       
   725     {
       
   726         switch(xmlnode_get_type(node))
       
   727         {
       
   728         case NTYPE_ATTRIB:
       
   729             xmlnode_put_attrib(parent, xmlnode_get_name(node), xmlnode_get_data(node));
       
   730             break;
       
   731         case NTYPE_TAG:
       
   732             xmlnode_insert_tag_node(parent, node);
       
   733             break;
       
   734         case NTYPE_CDATA:
       
   735             xmlnode_insert_cdata(parent, xmlnode_get_data(node), xmlnode_get_datasz(node));
       
   736         }
       
   737         node = xmlnode_get_nextsibling(node);
       
   738     }
       
   739 }
       
   740 
       
   741 
       
   742 /* produce full duplicate of x with a new pool, x must be a tag! */
       
   743 xmlnode xmlnode_dup(xmlnode x)
       
   744 {
       
   745     xmlnode x2;
       
   746 
       
   747     if(x == NULL)
       
   748         return NULL;
       
   749 
       
   750     x2 = xmlnode_new_tag(xmlnode_get_name(x));
       
   751 
       
   752     if (xmlnode_has_attribs(x))
       
   753         xmlnode_insert_node(x2, xmlnode_get_firstattrib(x));
       
   754     if (xmlnode_has_children(x))
       
   755         xmlnode_insert_node(x2, xmlnode_get_firstchild(x));
       
   756 
       
   757     return x2;
       
   758 }
       
   759 
       
   760 xmlnode xmlnode_dup_pool(pool p, xmlnode x)
       
   761 {
       
   762     xmlnode x2;
       
   763 
       
   764     if(x == NULL)
       
   765         return NULL;
       
   766 
       
   767     x2 = xmlnode_new_tag_pool(p, xmlnode_get_name(x));
       
   768 
       
   769     if (xmlnode_has_attribs(x))
       
   770         xmlnode_insert_node(x2, xmlnode_get_firstattrib(x));
       
   771     if (xmlnode_has_children(x))
       
   772         xmlnode_insert_node(x2, xmlnode_get_firstchild(x));
       
   773 
       
   774     return x2;
       
   775 }
       
   776 
       
   777 xmlnode xmlnode_wrap(xmlnode x,const char *wrapper)
       
   778 {
       
   779     xmlnode wrap;
       
   780     if(x==NULL||wrapper==NULL) return NULL;
       
   781     wrap=xmlnode_new_tag_pool(xmlnode_pool(x),wrapper);
       
   782     if(wrap==NULL) return NULL;
       
   783     wrap->firstchild=x;
       
   784     wrap->lastchild=x;
       
   785     x->parent=wrap;
       
   786     return wrap;
       
   787 }
       
   788 
       
   789 void xmlnode_free(xmlnode node)
       
   790 {
       
   791     if(node == NULL)
       
   792         return;
       
   793 
       
   794     pool_free(node->p);
       
   795 }