📄 xmlnode.c
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "JOSL"). You may not copy or use this file, in either * source code or executable form, except in compliance with the JOSL. You * may obtain a copy of the JOSL at http://www.jabber.org/ or at * http://www.opensource.org/. * * Software distributed under the JOSL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL * for the specific language governing rights and limitations under the * JOSL. * * Copyrights * * Portions created by or assigned to Jabber.com, Inc. are * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact * information for Jabber.com, Inc. is available at http://www.jabber.com/. * * Portions Copyright (c) 1998-1999 Jeremie Miller. * * Acknowledgements * * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. * * Alternatively, the contents of this file may be used under the terms of the * GNU General Public License Version 2 or later (the "GPL"), in which case * the provisions of the GPL are applicable instead of those above. If you * wish to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the JOSL, * indicate your decision by deleting the provisions above and replace them * with the notice and other provisions required by the GPL. If you do not * delete the provisions above, a recipient may use your version of this file * under either the JOSL or the GPL. * * * --------------------------------------------------------------------------*/#include "lib.h"/* Internal routines */xmlnode _xmlnode_new(pool p, const char* name, unsigned int type){ xmlnode result = NULL; if (type > NTYPE_LAST) return NULL; if (type != NTYPE_CDATA && name == NULL) return NULL; if (p == NULL) { p = pool_heap(1*1024); } /* Allocate & zero memory */ result = (xmlnode)pmalloco(p, sizeof(_xmlnode)); /* Initialize fields */ if (type != NTYPE_CDATA) result->name = pstrdup(p,name); result->type = type; result->p = p; return result;}static xmlnode _xmlnode_append_sibling(xmlnode lastsibling, const char* name, unsigned int type){ xmlnode result; result = _xmlnode_new(xmlnode_pool(lastsibling), name, type); if (result != NULL) { /* Setup sibling pointers */ result->prev = lastsibling; lastsibling->next = result; } return result;}static xmlnode _xmlnode_insert(xmlnode parent, const char* name, unsigned int type){ xmlnode result; if(parent == NULL || (type != NTYPE_CDATA && name == NULL)) return NULL; /* If parent->firstchild is NULL, simply create a new node for the first child */ if (parent->firstchild == NULL) { result = _xmlnode_new(parent->p, name, type); parent->firstchild = result; } /* Otherwise, append this to the lastchild */ else { result= _xmlnode_append_sibling(parent->lastchild, name, type); } result->parent = parent; parent->lastchild = result; return result;}static xmlnode _xmlnode_search(xmlnode firstsibling, const char* name, unsigned int type){ xmlnode current; /* Walk the sibling list, looking for a NTYPE_TAG xmlnode with the specified name */ current = firstsibling; while (current != NULL) { if ((current->type == type) && (j_strcmp(current->name, name) == 0)) return current; else current = current->next; } return NULL;}void _xmlnode_merge(xmlnode data){ xmlnode cur; char *merge, *scur; int imerge; /* get total size of all merged cdata */ imerge = 0; for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next) imerge += cur->data_sz; /* copy in current data and then spin through all of them and merge */ scur = merge = pmalloc(data->p,imerge + 1); for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next) { memcpy(scur,cur->data,cur->data_sz); scur += cur->data_sz; } *scur = '\0'; /* this effectively hides all of the merged-in chunks */ data->next = cur; if(cur == NULL) data->parent->lastchild = data; else cur->prev = data; /* reset data */ data->data = merge; data->data_sz = imerge; }static void _xmlnode_hide_sibling(xmlnode child){ if(child == NULL) return; if(child->prev != NULL) child->prev->next = child->next; if(child->next != NULL) child->next->prev = child->prev;}void _xmlnode_tag2str(spool s, xmlnode node, int flag){ xmlnode tmp; if(flag==0 || flag==1) { spooler(s,"<",xmlnode_get_name(node),s); tmp = xmlnode_get_firstattrib(node); while(tmp) { spooler(s," ",xmlnode_get_name(tmp),"='",strescape(xmlnode_pool(node),xmlnode_get_data(tmp)),"'",s); tmp = xmlnode_get_nextsibling(tmp); } if(flag==0) spool_add(s,"/>"); else spool_add(s,">"); } else { spooler(s,"</",xmlnode_get_name(node),">",s); }}spool _xmlnode2spool(xmlnode node){ spool s; int level=0,dir=0; xmlnode tmp; if(!node || xmlnode_get_type(node)!=NTYPE_TAG) return NULL; s = spool_new(xmlnode_pool(node)); if(!s) return(NULL); while(1) { if(dir==0) { if(xmlnode_get_type(node) == NTYPE_TAG) { if(xmlnode_has_children(node)) { _xmlnode_tag2str(s,node,1); node = xmlnode_get_firstchild(node); level++; continue; }else{ _xmlnode_tag2str(s,node,0); } }else{ spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node))); } } tmp = xmlnode_get_nextsibling(node); if(!tmp) { node = xmlnode_get_parent(node); level--; if(level>=0) _xmlnode_tag2str(s,node,2); if(level<1) break; dir = 1; }else{ node = tmp; dir = 0; } } return s;}/* External routines *//* * xmlnode_new_tag -- create a tag node * Automatically creates a memory pool for the node. * * parameters * name -- name of the tag * * returns * a pointer to the tag node * or NULL if it was unsuccessfull */xmlnode xmlnode_new_tag(const char* name){ return _xmlnode_new(NULL, name, NTYPE_TAG);}/* * xmlnode_new_tag_pool -- create a tag node within given pool * * parameters * p -- previously created memory pool * name -- name of the tag * * returns * a pointer to the tag node * or NULL if it was unsuccessfull */xmlnode xmlnode_new_tag_pool(pool p, const char* name){ return _xmlnode_new(p, name, NTYPE_TAG);}/* * xmlnode_insert_tag -- append a child tag to a tag * * parameters * parent -- pointer to the parent tag * name -- name of the child tag * * returns * a pointer to the child tag node * or NULL if it was unsuccessfull */xmlnode xmlnode_insert_tag(xmlnode parent, const char* name){ return _xmlnode_insert(parent, name, NTYPE_TAG);}/* * xmlnode_insert_cdata -- append character data to a tag * * parameters * parent -- parent tag * CDATA -- character data * size -- size of CDATA * or -1 for null-terminated CDATA strings * * returns * a pointer to the child CDATA node * or NULL if it was unsuccessfull */xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size){ xmlnode result; if(CDATA == NULL || parent == NULL) return NULL; if(size == -1) size = strlen(CDATA); result = _xmlnode_insert(parent, NULL, NTYPE_CDATA); if (result != NULL) { result->data = (char*)pmalloc(result->p, size + 1); memcpy(result->data, CDATA, size); result->data[size] = '\0'; result->data_sz = size; } return result;}/* * xmlnode_get_tag -- find given tag in an xmlnode tree * * parameters * parent -- pointer to the parent tag * name -- "name" for the child tag of that name * "name/name" for a sub child (recurses) * "?attrib" to match the first tag with that attrib defined * "?attrib=value" to match the first tag with that attrib and value * "=cdata" to match the cdata contents of the child * or any combination: "name/name/?attrib", "name=cdata", etc * * results * a pointer to the tag matching search criteria * or NULL if search was unsuccessfull */xmlnode xmlnode_get_tag(xmlnode parent, const char* name){ char *str, *slash, *qmark, *equals; xmlnode step, ret; if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL; if(strstr(name, "/") == NULL && strstr(name,"?") == NULL && strstr(name, "=") == NULL) return _xmlnode_search(parent->firstchild, name, NTYPE_TAG); str = strdup(name); slash = strstr(str, "/"); qmark = strstr(str, "?"); equals = strstr(str, "="); if(equals != NULL && (slash == NULL || equals < slash) && (qmark == NULL || equals < qmark)) { /* of type =cdata */ *equals = '\0'; equals++; for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) { if(xmlnode_get_type(step) != NTYPE_TAG) continue; if(*str != '\0') if(j_strcmp(xmlnode_get_name(step),str) != 0) continue; if(j_strcmp(xmlnode_get_data(step),equals) != 0) continue; break; } free(str); return step; } if(qmark != NULL && (slash == NULL || qmark < slash)) { /* of type ?attrib */ *qmark = '\0'; qmark++; if(equals != NULL) { *equals = '\0'; equals++; } for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) { if(xmlnode_get_type(step) != NTYPE_TAG) continue; if(*str != '\0') if(j_strcmp(xmlnode_get_name(step),str) != 0) continue; if(xmlnode_get_attrib(step,qmark) == NULL) continue; if(equals != NULL && j_strcmp(xmlnode_get_attrib(step,qmark),equals) != 0) continue; break; } free(str); return step; } *slash = '\0'; ++slash;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -