一个关于xml解析的程序
#include<stdio.h>#include<string.h>
#include<stdlib.h>
#define M 100
const m=10;
#define empty -1
#define succ 1
#define fail 0
#include<ctype.h>
//#define N 10000
typedef struct Dtnode
{
int level;
char node[50];
struct Dtnode *next,*value,*lang,*down;
}Dtnode,*Dtptr;
int push(int num[],int &top,int x)
{
if(top==m-1)return fail;
num[++top]=x; //测试代码 printf("/%d\n",num[top]);
return succ; //测试代码 printf("//num[top]=%d",num[top]);
} //进站函数,top为数组下标,数字数组
int pop(int num[],int &top,int &x)
{
if(top==empty)return fail; //测试代码 printf("测试num[top]=%d top=%d测试\n",num[top],x);
x=num[top--]; //测试代码 printf("测试num[top]=%d top=%d测试\n",num[top],x);
return succ;
} //退站函数,top为数组下标,数字数组
void jiexi_str(char str[],int top,Dtptr &p,Dtptr &root,int different,Dtptr &level2)
{
int i=0,j=0;
while(str[i]!='\0')
{
i++;
if(str[i]=='"')
break;
}
if(str[i]=='"')
{
//Dtptr q;
int k=i;
char strr[100];
i=0;
while(str[i]!=' ')
{
strr[i]=str[i];
i++;
}
strr[i]='\0'; //printf("%d a ",top);puts(strr);//测试代码 //printf("解析levle str\n");
//strr把元素取走
switch(top)
{
case 2:
{ //元素节点
Dtptr q;
q=new Dtnode;
strcpy(q->node,strr);
//puts(q->node);
q->level=2;
level2=q;
if(p->level==1)
{
p->next=q;
q->next=p;
p=p->next;
}
if(p->level==3)
{
p=p->down;
p->next=q;
q->next=root;
p=p->next;
}
break;
}
case 3:
{ //元素节点
Dtptr q;
q=new Dtnode;
q->next=NULL;
p->down=q;
strcpy(q->node,strr);
//puts(q->node);
q->down=level2;
q->level=3;
p=p->down;
break;
}
default:
{
printf("ERROR\n");
exit(0);
}
}
j=0;
i++;
while(str[i]!='=')
{
strr[j]=str[i];
i++,j++;
}
strr[j]='\0'; //测试代码 puts(strr);//printf("解析level value str\n");
//不需取走这个strr
k++,j=0;
while(str[k]!='"')
{
strr[j]=str[k];
j++,k++;
}
strr[j]='\0'; // printf("%d b ",top);puts(strr); //测试代码 //printf("解析 lang str\n");
//strr把属性取走
switch(top)
{
case 2:
{ //值节点。属性域置空
p->value=NULL;
Dtptr q;
q=new Dtnode;
q->down=q->lang=q->next=q->value=NULL;
strcpy(q->node,strr);
//puts(q->node);
p->lang=q;
break;
}
case 3:
{ //属性节点
Dtptr q;
q=new Dtnode;
q->down=q->lang=q->next=q->value=NULL;
strcpy(q->node,strr);
//puts(q->node);printf("测试");
p->lang=q;
break;
}
default:
{
printf("ERROR\n");
exit(0);
}
}
}
else
{
printf("%d c ",top);puts(str); //测试代码 //str直接建节点 分清level=1、2 和level =3是不同的
switch(top)
{
case 1:
{ //根节点。属性域,值域均置空
p=new Dtnode;
strcpy(p->node,str);
p->lang=p->value=p->down=NULL;
p->level=1;
root=p;
break;
}
case 3:
{ //判断different,如果 different=2 值节点。属性域置空,如果 元素节点 different=1不置空
Dtptr q;
q=new Dtnode;
strcpy(q->node,str);
//puts(q->node);
if(different==2)
{
p->value=q;
q->down=q->lang=q->next=q->value=NULL;
//p->lang=NULL;///????
}
else
{
p->down=q;
q->next=NULL;
q->lang=NULL;
q->level=3;
q->down=level2;
p=p->down;
}
break;
}
default:
{
printf("ERROR\n");
exit(0);
}
}
}
}
void bianli(Dtptr p)
{
if(p==NULL)
return;
if(p->level!=2)
puts(p->node);
bianli(p->value);
//bianli(p->lang);
if(p->down==NULL)
return;
//printf("1");
if(p->down->level==2)
return;
if(p->down->level!=2)
bianli(p->down);
}
void output_bianli(Dtptr root)
{
Dtptr p;
p=root;
puts(p->node);
while(1)
{
p=p->next;
if(p==root)
break;
else
bianli(p);
}
}
void search_bianli(Dtptr p,Dtptr q,int &record,char name[])
{
Dtptr root=q;
if(p==NULL)
return;
//puts(p->node);
if(strcmp(p->node,name)==0)
{
//q=p;
record=1;
printf("节点存在,请选择操作\n");
printf("1、修改2、删除\n");
int g;
char newname[M];
scanf("%d",&g);
switch(g)
{
case 1:
{
printf("若存在多个相同名称的节点,则按建表顺序依次进行操作\n");
char ch=getchar();
printf("请输入修改的值\n");
gets(newname);
strcpy(p->node,newname);
printf("修改后的文本为\n");
output_bianli(q);
break;
}
case 2:
{
//判断找到的节点是什么类型的节点
printf("仅支持对相应文本所在的level=2的节点的删除。eg:bookstore中对Harry Potter这本书的删除\n");
printf("若输入book,title,author,year等节点,删除后将整个树删除\n");//puts(name);
if(strcmp(q->node,name)==0)
{
printf("节点不可操作\n");
exit(0);
}
Dtptr p,r;
int record=0;
p=root;
while(1)
{
p=p->next;
if(root==p)
break;
r=p;
while(1)
{
//q=r;
r=r->down;
if(p==r)
break;/////////
if(strcmp(r->node,name)==0)
{
while(root->next!=p)
root=root->next; //puts(r->node);
root->next=p->next;
delete p;
record=1;
break;
}
if(r->lang!=NULL)
if(strcmp(r->lang->node,name)==0)
{
while(root->next!=p)
root=root->next; // puts(r->node);
root->next=p->next;
delete p;
record=1;
break;
}
if(r->value!=NULL)
if(strcmp(r->value->node,name)==0)
{
while(root->next!=p)
root=root->next; //puts(r->node);
root->next=p->next;
delete p;
record=1;
break;
}
if(record)
break;
}
if(record)
break;
}
printf("删除后的文本为\n");
output_bianli(q);
exot(0);
}
default:exit(0);
}
}
search_bianli(p->value,q,record,name);
search_bianli(p->lang,q,record,name);
if(p->down==NULL)
return;
if(p->down->level==2)
return;
else
search_bianli(p->down,q,record,name);
}
void search(Dtptr root,char name[])
{
char c;
int record=0; //printf("1");
printf("修改和删除输入1 插入输入2\n");
int t;
scanf("%d",&t);
if(t==1)
{
int h=0;
c=getchar();
printf("请输入要操作的节点名\n");
c=getchar();
while(c!='\n')
{
name[h++]=c;
c=getchar();
}
name[h]='\0';
//puts(name);
Dtptr p;
p=root;
if(strcmp(p->node,name)==0)
{
printf("该节点为根节点,不予操作\n");
exit(0);
}
while(1)
{
p=p->next;
if(p==root)
{
printf("该节点不存在或不再有相同名称节点\n");
break;
}
search_bianli(p,root,record,name);
}
}
if(t==2)
{
printf("仅支持第二层节点的插入\n");
int j;
printf("插在根节点后第一个输入1,最后一个输入2\n");
scanf("%d",&j);
switch(j)
{
case 1:
{
Dtptr p,q;
p=new Dtnode;
p->next=root->next;
root->next=p;
char str[]="new Dtnode";
strcpy(p->node,str);
p->lang=p->value=NULL;
p->level=2;
q=new Dtnode;
p->down=q;
q->down=p;
q->lang=q->value=NULL;
q->level=3;
strcpy(q->node,str);puts(q->node);
printf("其他操作按dom tree 建立方式建立,属重复操作,输出时会看到new Dtnode节点的输出\n");
printf("插入后为\n");
output_bianli(root);
}
case 2:
{
Dtptr r;
r=root;
while(1)
{
if(r->next==root)
break;
r=r->next;
}
Dtptr p,q;
p=new Dtnode;
p->next=r->next;
r->next=p;
char str[]="new Dtnode";
strcpy(p->node,str);
p->lang=p->value=NULL;
p->level=2;
q=new Dtnode;
p->down=q;
q->down=p;
q->lang=q->value=NULL;
q->level=3;
strcpy(q->node,str);puts(q->node);
printf("其他操作按dom tree 建立方式建立,属重复操作,输出时会看到new Dtnode节点的输出\n");
printf("插入后为\n");
output_bianli(root);
break;
}
}
}
}
void main()
{
printf("输出文本信息\n");
Dtptr p,root,level2;
FILE *pf;
char ch,str[M];
int i=0,s[100],top=-1,n=1,x,end=1,different;
if((pf=fopen("file.txt","r"))==NULL)
{
printf("can not open the file\n");
exit(0);
}
/*提前将0进栈*/
if(push(s,top,0)!=1)
{
printf("ERROR\n");
exit(0);
} //测试代码printf("1");
while(1)
{
if(n)
{
ch=fgetc(pf);
if(feof(pf))
break;
} // printf("d");putchar(ch);printf("d\n");测试代码putchar(ch);
if(ch==' '||ch=='\n')
continue;
if(ch=='<')
{
different=1;
n=1;
ch=fgetc(pf);
if(ch!='/')
{ //printf("s[top]=%d",s[top]);
x=s[top]+1; //printf("x=%4d",x);
if(push(s,top,x)!=1) //top++进栈
{
printf("ERROR\n");
exit(0);
} //printf("进栈top%ds[top]%d\n",top,s[top]);
i=0;
while(ch!='>')
{
str[i]=ch;
i++;
ch=fgetc(pf);
}
str[i]='\0';
//puts(str); //测试代码printf("f");puts函数输出后自动换行
}
else
{ //printf("出栈前top%d=s[top]%d\n",top,s[top]);
x=s[top];
if(pop(s,top,x)!=1) //top出栈
{
printf("ERROR\n");
exit(0);
} //printf("出栈top%d===s[top]%d\n",top,s[top]);
while(ch!='>')
ch=fgetc(pf);
end=0;
}
}
else
{
different=2;
i=0;
while(ch!='<')
{
str[i]=ch;
i++;
ch=fgetc(pf);
}
str[i]='\0';
//puts(str);
n=0;
} //printf("ERROR\n");这里的top是不变的,所以在switch时要考虑怎样让这个case 3 成功执行
if(end)
jiexi_str(str,top,p,root,different,level2); //解析str,分离出str中有用的信息
end=1;
}
printf("文本信息检查结束,输入 1:清屏 0:继续\n");
int w;
scanf("%d",&w);
if(w)
system("CLS");
else
;
//遍历输出
printf("建立的树为\n");
output_bianli(root);
Dtptr q=root;
char name[M];
search(root,name);
}
一个简单的xlm解析器
文档结构:
<bookstore>
<book category="children">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="web">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
时间太少了,写的很匆忙。。。哪位有好一点的方式做啊。。。
目标就是建立一棵dom tree
能够解析文档,并且支持插入删除和修改(本人觉得插入和删除就是扯淡。。。)
老师留的作业。。。没办法。。。
版本信息不用做~
[ 本帖最后由 qldxsun 于 2011-6-9 23:10 编辑 ]