📄 xml.c
字号:
#include "xml.h"//#define DEBUGstatic char* align_string(char* pTemp){ int i = 0; while(pTemp[i] == ' ') i++; return pTemp+i;}static int verifyxmlfile(int fd){ FILE* fp = fdopen(fd,"r"); char buf[255]; memset(buf,0,255); if(!(fgets(buf,255,fp))) { return -1; } if(strncmp(buf,"<?",2) || !strstr(buf,"?>")) { return -1; } if(!strstr(buf,"Xml") && !strstr(buf,"xml")) { return -1; } return 0;}static struct element* tonext(struct element* elem,int* layer){ struct element* cur = NULL,*next = NULL; cur = elem; upfloor: (*layer)--; next = cur->parent; if(!next) return NULL; if(next->brothers) return next->brothers; cur = next; goto upfloor;}//***************************************************************************//1.struct xml* readxmlfile(char* filename){ struct xml* myxml = NULL; int fd,size; struct stat s; if(!filename || (fd = open(filename,O_RDONLY)) < 0) { return NULL; } if(verifyxmlfile(fd) < 0) { fprintf(stderr,"verify xml file %s error!\n",filename); close(fd); return NULL; } if(!(myxml = malloc(sizeof(struct xml)))) { close(fd); return NULL; } memset(myxml,0,sizeof(struct xml)); strcpy(myxml->filename,filename); myxml->root = myxml->current = NULL; fstat(fd,&s); myxml->size = s.st_size; if(!(myxml->data = malloc(myxml->size + 10))) { free(myxml); close(fd); return NULL; } lseek(fd,0,SEEK_SET); size = read(fd,myxml->data,myxml->size); if(size != myxml->size) { fprintf(stderr,"read xml file %s failed\n",myxml->filename); close(fd); free(myxml->data); free(myxml); return NULL; } close(fd); return myxml; }static void freeelement(struct element* cur){ struct element_property* ep = cur->property,*next = NULL; while(ep) { next = ep->next; free(ep); ep = next; } free(cur); return;}//***************************************************************************//2.int closexml(struct xml* myxml){ struct element *cur,*next,*parent; if(!(myxml->data)) free(myxml->data); cur = myxml->root; while(cur) { if(cur->children) cur = cur->children; else if(cur->brothers) { next = cur->brothers; parent = cur->parent; parent->children = next; #ifdef DEBUG fprintf(stderr,"free element:%s success\n",cur->name); #endif freeelement(cur); cur = next; } else { next = cur->parent; if(next) next->children = NULL; #ifdef DEBUG fprintf(stderr,"free element:%s success\n",cur->name); #endif freeelement(cur); cur = next; } } free(myxml); return 0;}#define STATE_WILL_START 0#define STATE_ELEM_NAME 1#define STATE_ELEM_NAME_END 2#define STATE_PROP_NAME 3#define STATE_PROP_NAME_END 4#define STATE_PROP_VALUE 5#define STATE_PROP_VALUE_END 6#define STATE_PROP_ONE_END 7#define STATE_PROP_END 8#define STATE_ELEM_VALUE 9#define STATE_ELEM_VALUE_END 10#define STATE_ELEM_END 11#define STATE_END 12#define KINDRED_PC 1 //parent--child#define KINDRED_CP 2 //child---parentstruct __control { int layer; //0: top layer int state; // int kindred; //前一个元素和新元素的关系;};static int findendtag(char* data,char* tag){ char buf[ELEMENT_MAX_SIZE + 5]; int n; n = sprintf(buf,"</%s>",tag); buf[n] = '\0'; if((strstr(data,buf))) return 0; else return -1;}//***************************************************************************//3.int parsexmlfile(struct xml* myxml){ char* data,*offset,*tmp; char suffix,buffer[512]; int size,count = 0; struct element* current= NULL,*parent = NULL; struct element_property* cur_property = NULL; char* pos = NULL; int n; struct __control control; if(!myxml->data) return -1; control.layer = 0; control.state = STATE_WILL_START; control.kindred = 0; data = offset = myxml->data; size = myxml->size; #ifdef DEBUG fprintf(stderr,"=============>data begin address:%p\tsize:%d\n",data,size); #endif while((offset - data) < size ) { switch(control.state) { case STATE_WILL_START: findroot: if(!(tmp = strchr(offset,'<'))) return -1; suffix = *(tmp + 1); if(suffix == '?' || suffix == '!') { offset = tmp + 1; goto findroot; } if(suffix == ' ') return -1; offset = tmp + 1; count = 0; control.state = STATE_ELEM_NAME; break; case STATE_ELEM_NAME: if(*offset != ' ' && *offset != '>' && *offset != '/') { buffer[count++] = *offset; offset++; } else { buffer[count] = '\0'; count = 0; control.state = STATE_ELEM_NAME_END; } break; case STATE_ELEM_NAME_END: control.layer++; parent = current; if(!(current = (struct element*)malloc(sizeof(struct element)))) { #ifdef DEBUG fprintf(stderr,"malloc memory of element<%s>failed!\n", buffer); #endif return -1; } strcpy(current->name,buffer); current->property = NULL; current->value_size = findendtag(offset,buffer); current->value[0] = '\0'; current->parent = NULL; current->children = NULL; current->brothers = NULL; current->reserve = NULL; #ifdef DEBUG fprintf(stderr,"get one element: name %s \tlayer:%d\n", current->name,control.layer); #endif if(control.layer == 1) { current->parent = NULL; myxml->root = current; parent = current; } else { if(!parent->children) { current->parent = parent; parent->children = current; parent->reserve = current; } else { current->parent = parent; parent->reserve->brothers = current; parent->reserve = current; } } control.state = STATE_PROP_ONE_END; break; case STATE_PROP_NAME: offset = align_string(offset); if(*offset == '>' || *offset == '/') { return -1; } if(*offset != '=') { buffer[count++] = *offset; offset++; } else { buffer[count] = '\0'; count = 0; control.state = STATE_PROP_NAME_END; } break; case STATE_PROP_NAME_END: #ifdef DEBUG fprintf(stderr,"\tproperty name:%s\t",buffer); #endif if(!(cur_property = malloc(sizeof(struct element_property)))) { fprintf(stderr,"malloc memory of property <%s> failed!\n", buffer); return -1; } strcpy(cur_property->name,buffer); cur_property->value[0] = '\0'; cur_property->next = current->property; current->property = cur_property; offset++; count = 0; control.state = STATE_PROP_VALUE; break; case STATE_PROP_VALUE: if(*offset != ' ' && *offset != '>' && *offset != '/') { if(*offset == '"') { offset++; break; } buffer[count++] = *offset; offset++; } else { buffer[count] = '\0'; count = 0; control.state = STATE_PROP_VALUE_END; } break; case STATE_PROP_VALUE_END: #ifdef DEBUG fprintf(stderr,"value:%s\n",buffer); #endif strcpy(current->property->value,buffer); control.state = STATE_PROP_ONE_END; break; case STATE_PROP_ONE_END: offset = align_string(offset); if(*offset == '>') { offset++; control.state = STATE_PROP_END; } else if(*offset == '/' && *(offset + 1) == '>') { if(control.layer == 1) { #ifdef DEBUG fprintf(stderr,"parse xml success!\n"); #endif control.state = STATE_END; } else { control.layer--; current = parent; parent = parent->parent; if(!parent) parent = myxml->root; control.kindred = KINDRED_CP; control.state = STATE_ELEM_END; offset += 2; } } else control.state = STATE_PROP_NAME; break; case STATE_PROP_END: if(*offset == '\r' || *offset == '\n' || *offset == '\t' || *offset == ' ') { offset++; break; } count = 0; control.state = STATE_ELEM_VALUE; break; case STATE_ELEM_VALUE: if(*offset != '<') { buffer[count++] = *offset; offset++; } else { if(!strncmp(offset,"<!--",4)) { if(!(pos = strstr(offset,"-->"))) return -1; offset = pos + 3; delspecial: if(*offset == '\r' || *offset == '\n' || *offset == '\t' || *offset == ' ') { offset++; goto delspecial; } break; } buffer[count] = '\0'; if(count > 0) { strcat(current->value,buffer); #ifdef DEBUG fprintf(stderr,"\tget element value: %s\tcount:%d\n", current->value,count); #endif } count = 0; control.state = STATE_ELEM_VALUE_END; } break; case STATE_ELEM_VALUE_END: if(*(offset + 1) == '/') { #ifdef DEBUG fprintf(stderr,"child %s layer:%d ---> parent\n", current->name,control.layer); #endif n = sprintf(buffer,"</%s>",current->name); buffer[n] = '\0'; if((strncmp(offset,buffer,strlen(buffer)))) { fprintf(stderr,"error:find tag %s failed!\n",buffer); return -1; } if(control.layer == 1) { #ifdef DEBUG fprintf(stderr,"parse xml success!\n"); #endif control.state = STATE_END; } else { control.layer--; current = parent; parent = parent->parent; if(!parent) parent = myxml->root; control.kindred = KINDRED_CP; control.state = STATE_ELEM_END; offset += n; } } else { #ifdef DEBUG fprintf(stderr,"parent %s ---> children\n",current->name); #endif control.kindred = KINDRED_PC; control.state = STATE_ELEM_NAME; offset++; } break; case STATE_ELEM_END: control.state = STATE_PROP_END; break; case STATE_END: free(myxml->data); myxml->data = NULL; return 0; break; default: offset++; break; } } return 0;}//***************************************************************************//4.int traversalxml(struct xml* myxml){ int layer = 0; struct element *cur,*next; char* tmp = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; char buf[16]; if(!myxml) return -1; cur = myxml->root; while(cur) { memset(buf,0,16); strncpy(buf,tmp,layer); fprintf(stderr,"%s%s\tvalue:%s\n",buf,cur->name,cur->value); if(cur->children) { layer++; cur = cur->children; } else if(cur->brothers) { cur = cur->brothers; } else { if(!(next = tonext(cur,&layer))) return 0; cur = next; } } return 0;}//***************************************************************************//5.int getcurrentelement(struct xml* myxml,char* name,char* value){ if(!myxml || !myxml->current || !name) return -1; strcpy(name,myxml->current->name); if(!value) strcpy(value,myxml->current->value); return 0;}//***************************************************************************//6.int getcurrentpath(struct xml* myxml,char* path,int size){ struct element *real[16],*cur; int n,i,len = 0; if(!myxml || !myxml->current || !path) return -1; path[0] = '\0'; cur = myxml->current; for(n = 0;n < 16;n++) { if(!cur) break; real[n] = cur; cur = cur->parent; } for(i = n - 2;i>= 0;i--) { len += strlen(real[i]->name) + 1; if(len >= size) return -1; strcat(path,real[i]->name); strcat(path,"/"); } return 0;}//***************************************************************************//7.int movetoroot(struct xml* myxml){ if(!myxml || !myxml->root) return -1; myxml->current = myxml->root; return 0;}//***************************************************************************//8.int movetoparent(struct xml* myxml){ struct element* parent; if(!myxml || !myxml->current) return -1; parent = myxml->current->parent; myxml->current = parent; return 0;}struct element* match(struct element* head,char* elem){ struct element* current = NULL; if(!head || !elem) return NULL; current = head; while(current) { if(!strcmp(current->name,elem)) return current; current = current->brothers; } return NULL;}//***************************************************************************//9.int movetochild(struct xml* myxml,char* elem){ struct element* cur = NULL; if(!myxml || !myxml->current || !elem) return -1; cur = myxml->current->children; if(!cur) return -1; cur = match(cur,elem); if(cur) { myxml->current = cur; return 0; } else return -1;}//***************************************************************************//10.int movetobrother(struct xml* myxml,char* elem){ struct element* cur = NULL; if(!myxml || !myxml->current || !elem) return -1; if(!strcmp(myxml->current->name,elem)) return 0; cur = myxml->current->parent; if(!cur) return -1; cur = cur->children; if(!cur) return -1; cur = match(cur,elem); if(cur) { myxml->current = cur; return 0; } else return -1;}//****************************************************************************//11.int movetofirstchild(struct xml* myxml){ if(!myxml || !myxml->current || !myxml->current->children) return -1; myxml->current = myxml->current->children; return 0;}//****************************************************************************//12.int movetonextbrother(struct xml* myxml){ if(!myxml || !myxml->current || !myxml->current->brothers) return -1; myxml->current = myxml->current->brothers; return 0;}//***************************************************************************//13.int getchildren(struct xml* myxml){ struct element* cur; if(!myxml || !myxml->current) return -1; cur = myxml->current->children; while(cur) { fprintf(stderr,"%s\t%s\n",cur->name,cur->value); cur = cur->brothers; } fprintf(stderr,"\n"); return 0;}//***************************************************************************//14.int getcurrentproperty(struct xml* myxml,char* name,char* value,int size){ struct element_property* ep; if(!myxml || !myxml->current || !name || !value) return -1; ep = myxml->current->property; while(ep) { if(!strcmp(ep->name,name) && (strlen(ep->value) < size)) { strcpy(value,ep->value); return 0; } } return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -