对上次那个xml操作类做了下更新,加了gettext,puttext,selectnodes等几个属性,修复了一些bug。 #include <iostream> #include <string> #include <vector> using namespace std; class xml; class nodecollect; class node{ public: string getattr(string); node* setattr(string,string); node* appned(node *); node* removechild(int); node* insert(int,node*); node *getnext(); node *getparent(); node *getprevious(); node *getchild(int); nodecollect *getnodebyname(string); int getcount(); string gettag(); string gettype(); node* removeattr(string); void remove(); int gettotlecount(); string gettext(); node *puttext(string); nodecollect *selectnodes(string); private: friend class xml; int count; node *child; node *next; node *parent; string data; string tag; string type; xml *x; }; class nodecollect{ public: nodecollect(); int getcount(); node *item(int); void push(node*); private: int count; vector<node*> v; }; class xml{ public: xml(); ~xml(); void loadstring(string); void scan(string); void out(string&,node *); node *getchild(int); nodecollect *getnodebyname(string); int getcount(); node *createnode(string); node *createtextnode(string); void loadfile(string); void savefile(string); void flush(); string gettext(); node *insertpi(); xml* append(node *); nodecollect *selectnodes(string); private: friend class node; node* root; int count; string text; void output(node *,string&); }; xml::xml(){ root=0; count=0; } xml::~xml(){ } void xml::loadstring(string s){ scan(s); } void xml::scan(string s){ int i=0; node *p=0; while(1){ if(i==s.length()){ break; } if(s[i]=='<' && s[i+1]!='/'){ node *n=new node; count++; n->next=0; n->child=0; n->count=0; n->x=this; n->type="node"; if(s[i+1]=='!'){ n->type="cdata"; } if(p){ n->parent=p; n->parent->count++; node *n1=p->child; if(n1){ while(n1->next){ n1=n1->next; } n1->next=n; }else{ p->child=n; } }else{ n->parent=0; if(!root){ root=n; }else{ node* n1=root; while(n1->next){ n1=n1->next; } n1->next=n; } } i++; while(s[i]!='>'){ if(s[i]!='/') n->data.append(1,s[i]); i++; } int index=n->data.find(' '); n->tag=n->data.substr(0,index!=-1?index:n->data.find('>')); if(s[i-1]!='/' && s[i-1]!='?' && s[i-1]!=']'){ p=n; } }else if(s[i]=='<' && s[i+1]=='/'){ if(p->parent){ p=p->parent; }else{ p=0; } while(s[i]!='>'){ char t=s[i]; i++; } }else if(s[i]!='/t' && s[i]!=' ' && s[i]!='/r' && s[i]!='/n'){ node *n=new node; count++; n->next=0; n->child=0; n->count=0; n->parent=p; n->x=this; n->type="text"; n->parent->count++; node *n1=p->child; if(n1){ while(n1->next){ n1=n1->next; } n1->next=n; }else{ p->child=n; } while(s[i]!='<'){ n->data.append(1,s[i]); i++; } for(int i1=n->data.length()-1;i1>=0;i1--){ if(n->data[i1]!='/t' && n->data[i1]!=' ' && n->data[i1]!='/r' && n->data[i1]!='/n'){ break; }else{ n->data.erase(i1,1); } } continue; } i++; } } void xml::out(string& s,node *n=0){ if(!n){ node *r=root; while(r){ output(r,s); s+="/r/n"; r=r->next; } } else{ output(n,s); } } void xml::output(node * n,string& s){ node *n1=n; int tab=0; if(n1->gettype()=="text"){ s=s+n1->data; return; }else if(n1->child){ s=s+"<"+n1->data+">"+"/r/n"; }else if(n1->gettag()=="?xml"){ s=s+"<"+n1->data+">"; return; }else{ s=s+"<"+n1->data+"/>"; return; } while(1){ if(n1->child){ n1=n1->child; tab++; for(int i1=0;i1<tab;i1++){ s=s+"/t"; } if(n1->type=="text"){ s=s+n1->data+"/r/n"; }else if(n1->gettype()=="cdata"){ s=s+"<"+n1->data+">/r/n"; }else{ if(n1->count>0){ s=s+"<"+n1->data+">"+"/r/n"; }else{ s=s+"<"+n1->data+"/>"+"/r/n"; } } }else if(n1->next && n1!=n){ if(n1->count>0){ for(int i2=0;i2<tab;i2++){ s=s+"/t"; } s=s+"</"+n1->tag+">"+"/r/n"; } n1=n1->next; for(int i1=0;i1<tab;i1++){ s=s+"/t"; } if(n1->type=="text"){ s=s+n1->data+"/r/n"; }else if(n1->gettype()=="cdata"){ s=s+"<"+n1->data+">/r/n"; }else{ if(n1->count>0){ s=s+"<"+n1->data+">"+"/r/n"; }else{ s=s+"<"+n1->data+"/>"+"/r/n"; } } }else{ //s=s+"</"+n1->tag+">"+"/r/n"; node *n2=n1->parent,*n3=0; if(n2 && n2!=n){ while(n2->next==0){ tab--; for(int i1=0;i1<tab;i1++){ s=s+"/t"; } s=s+"</"+n2->tag+">"+"/r/n"; n3=n2; n2=n2->parent; if(n2==n){ tab--; for(int i1=0;i1<tab;i1++){ s=s+"/t"; } s=s+"</"+n->tag+">"; goto a; } } tab--; for(int i1=0;i1<tab;i1++){ s=s+"/t"; } s=s+"</"+n2->tag+">"+"/r/n"; n1=n2->next; for(int i2=0;i2<tab;i2++){ s=s+"/t"; } if(n1->count>0){ s=s+"<"+n1->data+">"+"/r/n"; }else{ s=s+"<"+n1->data+"/>"+"/r/n"; } }else{ s=s+"</"+n->tag+">"; a: break; } } } } nodecollect *xml::selectnodes(string s){ nodecollect *nc=new nodecollect; int i=0; if(s[i]=='/' && s[i+1]=='/'){ int index=s.find('/',i+2); string s1; if(index!=-1){ s1=s.substr(2,index-2); }else{ s1=s.substr(2); } int i1=0; while(getchild(i1)){ node *n=getchild(i1); if(n->gettag()==s1){ if(index==-1){ nc->push(n); }else if(s[index+1]=='/'){ string s2=s.substr(index+2); for(int i2=0;i2<n->gettotlecount();i2++){ if(n->getchild(i2)->gettag()==s2){ nc->push(n->getchild(i2)); } } }else{ node *n1=n->child; string s2=s.substr(index+1); while(n1){ if(n1->gettag()==s2){ nc->push(n1); } n1=n1->next; } } } i1++; } }else{ int index=s.find('/',i+1); string s1; if(index!=-1){ s1=s.substr(1,index-1); }else{ s1=s.substr(1); } node *nn=root; while(nn){ node *n=nn; if(n->gettag()==s1){ if(index==-1){ nc->push(n); }else if(s[index+1]=='/'){ string s2=s.substr(index+2); for(int i2=0;i2<n->gettotlecount();i2++){ if(n->getchild(i2)->gettag()==s2){ nc->push(n->getchild(i2)); } } }else{ node *n1=n->child; string s2=s.substr(index+1); while(n1){ if(n1->gettag()==s2){ nc->push(n1); } n1=n1->next; } } } nn=nn->next; } } return nc; } int xml::getcount(){ return count; } node *xml::getchild(int i){ int i1=0; node *n=root; while(i1!=i){ if(!n){ return 0; } if(n->child){ n=n->child; }else{ if(n->next){ n=n->next; }else{ while(n->parent && n->parent->next==0){ n=n->parent; } if(n->parent){ n=n->parent->next; }else{ return 0; } } } i1++; } return n; } nodecollect *xml::getnodebyname(string s){ node *n1=root; nodecollect *nc=new nodecollect; if(n1->tag==s){ nc->push(n1); } while(1){ if(n1->child){ n1=n1->child; if(n1->tag==s){ nc->push(n1); } }else if(n1->next){ n1=n1->next; if(n1->tag==s){ nc->push(n1); } }else{ //cout<<"</"<<n1->tag<<">"<<endl; node *n2=n1->parent,*n3=0; if(n2){ while(n2->next==0){ n3=n2; n2=n2->parent; if(n2==0){ goto a; } } n1=n2->next; if(n1->tag==s){ nc->push(n1); } }else{ // cout<<"</"<<n1->tag<<">"<<endl; a: break; } } } return nc; } node *xml::createnode(string s){ node *n=new node; n->x=this; n->child=0; n->count=0; n->next=0; n->parent=0; n->type="node"; n->tag=s; n->data=s; return n; } node *xml::createtextnode(string s){ node *n=new node; n->x=this; n->child=0; n->count=0; n->next=0; n->parent=0; n->type="text"; n->data=s; return n; } void xml::loadfile(string s){ FILE *f=fopen(s.data(),"rb"); char buf[2048]={0}; fread(buf,1,2047,f); text+=buf; while(!feof(f)){ memset(buf,0,2048); fread(buf,1,2047,f); text+=buf; } fclose(f); loadstring(text); } void xml::savefile(string s){ flush(); FILE *f=fopen(s.data(),"wb"); // cout<<text.length()<<" "<<strlen(text.data()); fwrite(text.data(),1,text.length(),f); fclose(f); } void xml::flush(){ text=""; string s; node *r=root; while(r){ output(r,s); text+=s; s=""; text+="/r/n"; r=r->next; } //scan(text); } string xml::gettext(){ return text; } node *xml::insertpi(){ node * n=createnode("?xml"); n->setattr("version","1.0"); n->data+="?"; n->next=root; root=n; count++; return n; } xml* xml::append(node *n){ if(root){ node *n1=root; while(n1->next){ n1=n1->next; } n1->next=n; }else{ root=n; } count+=n->gettotlecount()+1; return this; } nodecollect::nodecollect(){ count=0; } int nodecollect::getcount(){ return count; } node *nodecollect::item(int i){ return v[i]; } void nodecollect::push(node* n){ v.push_back(n); count++; } node* node::appned(node *n){ if(child){ node *n1=child; while(n1->next){ n1=n1->next; } n1->next=n; count++; n->parent=this; x->count+=n->gettotlecount()+1; }else{ child=n; count++; n->parent=this; x->count+=n->gettotlecount()+1; } return this; } node* node::insert(int i,node *n){ if(i==0){ n->next=child; n->parent=this; count++; child=n; }else if(i==count){ appned(n); }else{ node *n1=child,*n2=0; int i1=0; while(i1!=i){ n2=n1; n1=n1->next; i1++; } n2->next=n; n->next=n1; count++; n->parent=this; } return this; } node* node::removechild(int i){ if(i==0){ node *n=child; child=child->next; count--; x->count=x->count-gettotlecount()-1; delete n; }else{ node *n=child,*n1=0; int i1=0; while(i1!=i){ n1=n; n=n->next; i1++; } n1->next=n->next; count--; x->count=x->count-gettotlecount()-1; delete n; } return this; } string node::getattr(string s){ string ss; char *i=strstr(data.data(),s.data()); c: if(i && (*(i-1)==' ' || *(i-1)=='/r' || *(i-1)=='/n' || *(i-1)=='/t') && (*(i+s.length())==' ' || *(i+s.length())=='=')){ char *i1=strstr(i+1,"/""); char *i2=strstr(i1+1,"/""); i1++; while(i1!=i2){ ss+=*i1; i1++; } }else{ if(i==0){ return ss; }else{ i=strstr(i+1,s.data()); goto c; } } return ss; } node* node::setattr(string k,string v){ char *i=strstr(data.data(),k.data()); c: if(i && (*(i-1)==' ' || *(i-1)=='/r' || *(i-1)=='/n' || *(i-1)=='/t') && (*(i+k.length())==' ' || *(i+k.length())=='=')){ char *i1=strstr(i+1,"/""); char *i2=strstr(i1+1,"/""); string d=i2; data=data.substr(0,i1-data.data()+1); data+=v; data+=d; }else{ if(i==0){ if(data.substr(data.length()-1,1)!="?"){ data=data+' '+k+"="+'/"'+v+'/"'; }else{ data=data.substr(0,data.length()-1)+' '+k+"="+'/"'+v+"/"?"; } }else{ i=strstr(i+1,k.data()); goto c; } } return this; } node* node::removeattr(string s){ char *i=strstr(data.data(),s.data()); c: if(i && (*(i-1)==' ' || *(i-1)=='/r' || *(i-1)=='/n' || *(i-1)=='/t') && (*(i+s.length())==' ' || *(i+s.length())=='=')){ char *i1=strstr(i+1,"/""); char *i2=strstr(i1+1,"/""); string d=i2+1; data=data.substr(0,i-data.data()-1); data+=d; }else{ if(i==0){ return this; }else{ i=strstr(i+1,s.data()); goto c; } } return this; } void node::remove(){ node *n=getparent(); if(n){ node *n1=getprevious(); if(n1){ n1->next=next; }else{ n->child=next; } n->count--; x->count=x->count-gettotlecount()-1; }else{ node *n1=getprevious(); if(n1){ n1->next=next; }else{ x->root=x->root->next; } x->count=x->count-gettotlecount()-1; } delete this; } node *node::getchild(int i){ int i1=-1; node *n=this; while(i1!=i){ if(n->child){ n=n->child; }else{ if(n->next){ n=n->next; }else{ while(n->parent && n->parent->next==0 && n->parent!=this){ n=n->parent; } if(n->parent!=this){ n=n->parent->next; }else{ return 0; } } } i1++; } return n; } nodecollect *node::getnodebyname(string s){ node *n1=this->child; nodecollect *nc=new nodecollect; if(n1->tag==s){ nc->push(n1); } while(1){ if(n1->child){ n1=n1->child; if(n1->tag==s){ nc->push(n1); } }else if(n1->next){ n1=n1->next; if(n1->tag==s){ nc->push(n1); } }else{ //cout<<"</"<<n1->tag<<">"<<endl; node *n2=n1->parent,*n3=0; if(n2 && n2!=this){ while(n2->next==0){ n3=n2; n2=n2->parent; if(n2==this){ goto a; } } n1=n2->next; if(n1->tag==s){ nc->push(n1); } }else{ // cout<<"</"<<n1->tag<<">"<<endl; a: break; } } } return nc; } int node::getcount(){ return count; } node *node::getnext(){ return next; } node *node::getparent(){ return parent; } node *node::getprevious(){ if(parent){ node *n=parent->child; while(n->next!=this){ n=n->next; } return n; }else{ node *n=x->getchild(0); while(n->next!=this){ n=n->next; } return n; } return 0; } string node::gettag(){ return tag; } string node::gettype(){ return type; } int node::gettotlecount(){ int i1=0; node *n=this->child; if(n) i1++; while(n){ if(n->child){ n=n->child; }else{ if(n->next){ n=n->next; }else{ while(n->parent && n->parent->next==0 && n->parent!=this){ n=n->parent; } if(n->parent!=this){ n=n->parent->next; }else{ break; } } } i1++; } return i1; } string node::gettext(){ string s; for(int i=0;i<gettotlecount();i++){ if(getchild(i)->gettype()=="text"){ s+=getchild(i)->data; } } return s; } node *node::puttext(string s){ node *n=x->createtextnode(s); insert(0,n); return this; } nodecollect *node::selectnodes(string s){ nodecollect *nc=new nodecollect; int i=0; if(s[i]=='/' && s[i+1]=='/'){ int index=s.find('/',i+2); string s1; if(index!=-1){ s1=s.substr(2,index-2); }else{ s1=s.substr(2); } int i1=0; while(getchild(i1)){ node *n=getchild(i1); if(n->gettag()==s1){ if(index==-1){ nc->push(n); }else if(s[index+1]=='/'){ string s2=s.substr(index+2); for(int i2=0;i2<n->gettotlecount();i2++){ if(n->getchild(i2)->gettag()==s2){ nc->push(n->getchild(i2)); } } }else{ node *n1=n->child; string s2=s.substr(index+1); while(n1){ if(n1->gettag()==s2){ nc->push(n1); } n1=n1->next; } } } i1++; } }else{ int index=s.find('/',i+1); string s1; if(index!=-1){ s1=s.substr(1,index-1); }else{ s1=s.substr(1); } node *nn=child; while(nn){ node *n=nn; if(n->gettag()==s1){ if(index==-1){ nc->push(n); }else if(s[index+1]=='/'){ string s2=s.substr(index+2); for(int i2=0;i2<n->gettotlecount();i2++){ if(n->getchild(i2)->gettag()==s2){ nc->push(n->getchild(i2)); } } }else{ node *n1=n->child; string s2=s.substr(index+1); while(n1){ if(n1->gettag()==s2){ nc->push(n1); } n1=n1->next; } } } nn=nn->next; } } return nc; } 本文有不足之处,还望大家多多指正。