C语言操作XML--libxml2---001

学生信息管理系统

这是我们老师的一个大作业,要求如下:

综合训练项目一 线性结构综合训练

目的和要求:线性结构是最基础,也是最重要的一种结构,通过此项训练让学生掌握线性结构的知识;要求编程实现学生成绩管理系统,使学生掌握线性结构的存储 及相关算法设计;设有一个学生文件,其结构为:学号、姓名、数学成绩、英语成绩、计算机成绩、总分、平均分、排名。要求用顺序和链式两种方式进行存储,并 在此基础上实现学生成绩的录入、保存、计算总分和平均分、排名、查询、统计等基本功能。

我最初的代码在:http://my.oschina.net/iamhere/blog/340999

而我现在写的带libxml2的代码如下:

test.c//程序入口,目前只是测试libxml2的部分

#include<stdio.h>
#include"stuxml.h"
#include"studentList.h"


intmain(void){
SLstulist=list_create_file("student.txt");
list_print(stulist);
man_create_list(stulist,"student.info.xml");



return0;
}


student.h//学生结构及其操作定义

/**
*@filestudent.h
*定义了保存学生信息的结构体\n
*操作学生信息的函数:
*
*
*
*@author小代码
*/
#ifndefSTUDENT_H_
#defineSTUDENT_H_
#include<stdbool.h>
/**
*@brief学生对象结构体定义
*/
structstudent{
/**@brief学号*/
intstu_id;
/**@brief姓名*/
charstu_name[10];
/**@brief数学成绩*/
doublestu_score_math;
/**@brief英语成绩*/
doublestu_score_english;
/**@brief计算机成绩*/
doublestu_score_computer;
/**@brief总成绩*/
doublestu_score_sum;
/**@brief平均成绩*/
doublestu_score_avg;
/**@brief排名*/
intstu_score_grade;
/**@brief直接前驱元素指针*/
structstudent*prev;
/**@brief直接后继元素指针*/
structstudent*next;
};
/**@brief学生结构体*/
typedefstructstudentSTU;
/**@brief学生结构体指针*/
typedefstructstudent*Stu;
/**
*@brief输出学生信息的标题
*/
voidprint_title();

/**
*@brief创建一个学生信息对象
*
*@paramstu_id学号
*@paramstu_name姓名
*@paramstu_score_math数学成绩
*@paramstu_score_english英语成绩
*@paramstu_score_computer计算机成绩
*
*@return指向学生对象结构体的指针
*@retvalNULL创建失败
*/
Stustu_create(intstu_id,charstu_name[20],doublestu_score_math,doublestu_score_english,doublestu_score_computer);
/**
*@brief输出一个学生的信息
*
*输出格式为每项占10个空格\n
*如果参数为空,则不输出任何内容
*
*@paramstu要输出信息的学生对象
*/
voidstu_print(Stustu);
/**
*@brief比较两个学生的平均分
*
*
*@paramstu1
*@paramstu2
*
*@return比较结果
*@retval1stu1->stu_score_avg>stu2->stu_score_avg
*@retval0stu1->stu_score_avg=stu2->stu_score_avg
*@retval-1stu1->stu_score_avg<stu2->stu_score_avg
*/
intstu_score_compare(Stustu1,Stustu2);

/**
*@brief交换两个学生对象的所有成员的值
*
*交换成功则返回0\n
*如果有任何一个参数为NULL,则返回-1
*
*@paramstu1
*@paramstu2
*
*@retval0交换成功
*@retval-1交换失败
*/
intstu_swap(Stustu1,Stustu2);
#endif/*STUDENT_H_*/

student.c//学生操作实现

#include"student.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/**
*@brief输出学生信息的标题
*/
voidprint_title(){
printf("%-10s","学号");
printf("%-10s","姓名");
printf("%-10s","数学");
printf("%-10s","英语");
printf("%-10s","计算机");
printf("%-10s","总分");
printf("%-10s","平均分");
printf("%-10s\n","排名");
}
/**
*@brief创建一个学生信息对象
*
*@paramstu_id学号
*@paramstu_name姓名
*@paramstu_score_math数学成绩
*@paramstu_score_english英语成绩
*@paramstu_score_computer计算机成绩
*
*@return指向学生对象结构体的指针
*@retvalNULL创建失败
*/
Stustu_create(intstu_id,charstu_name[10],doublestu_score_computer){
Stustu=(Stu)malloc(sizeof(STU));
if(NULL==stu){
printf("stu_create...动态分配内存失败!");
exit(-1);
}
stu->stu_id=stu_id;
strcpy(stu->stu_name,stu_name);
stu->stu_score_math=stu_score_math;
stu->stu_score_english=stu_score_english;
stu->stu_score_computer=stu_score_computer;
stu->stu_score_sum=stu->stu_score_math+stu->stu_score_english
+stu->stu_score_computer;
stu->stu_score_avg=stu->stu_score_sum/3;
stu->stu_score_grade=-1;
stu->prev=NULL;
stu->next=NULL;
returnstu;
}
/**
*@brief输出一个学生的信息
*
*输出格式为每项占10个空格\n
*如果参数为空,则不输出任何内容
*
*@paramstu要输出信息的学生对象
*/
voidstu_print(Stustu){
if(NULL==stu){
return;
}
printf("%-10d",stu->stu_id);
printf("%-10s",stu->stu_name);
printf("%-10.2f",stu->stu_score_math);
printf("%-10.2f",stu->stu_score_english);
printf("%-10.2f",stu->stu_score_computer);
printf("%-10.2f",stu->stu_score_sum);
printf("%-10.2f",stu->stu_score_avg);
printf("%-10d",stu->stu_score_grade);
putchar('\n');
}
/**
*@brief比较两个学生的平均分
*
*
*@paramstu1
*@paramstu2
*
*@return比较结果
*@retval1stu1->stu_score_avg>stu2->stu_score_avg
*@retval0stu1->stu_score_avg=stu2->stu_score_avg
*@retval-1stu1->stu_score_avg<stu2->stu_score_avg
*/
intstu_score_compare(Stustu1,Stustu2){
intresult=0;
if(stu1->stu_score_sum>stu2->stu_score_sum)
result=1;
if(stu1->stu_score_sum<stu2->stu_score_sum)
result=-1;
returnresult;
}

/**
*@brief交换两个学生对象的所有成员的值
*
*交换成功则返回0\n
*如果有任何一个参数为NULL,则返回-1
*
*@paramstu1
*@paramstu2
*
*@retval0交换成功
*@retval-1交换失败
*/
intstu_swap(Stustu1,Stustu2){
if(NULL==stu1||NULL==stu2){
return-1;
}
intid_tmp=stu1->stu_id;
stu1->stu_id=stu2->stu_id;
stu2->stu_id=id_tmp;
charname_tmp[10];
strcpy(name_tmp,stu1->stu_name);
strcpy(stu1->stu_name,stu2->stu_name);
strcpy(stu2->stu_name,name_tmp);
doublescore_tmp=stu1->stu_score_math;
stu1->stu_score_math=stu2->stu_score_math;
stu2->stu_score_math=score_tmp;
score_tmp=stu1->stu_score_english;
stu1->stu_score_english=stu2->stu_score_english;
stu2->stu_score_english=score_tmp;
score_tmp=stu1->stu_score_computer;
stu1->stu_score_computer=stu2->stu_score_computer;
stu2->stu_score_computer=score_tmp;
stu1->stu_score_sum=stu1->stu_score_math+stu1->stu_score_english
+stu1->stu_score_computer;
stu1->stu_score_avg=stu1->stu_score_sum/3;
stu2->stu_score_sum=stu2->stu_score_math+stu2->stu_score_english
+stu2->stu_score_computer;
stu2->stu_score_avg=stu2->stu_score_sum/3;
return0;
}


studentList.h//学生列表定义及其操作声明

/**
*@file
*定义了学生列表结构体
*
*@author小代码
*/
#ifndefSTUDENTLIST_H_
#defineSTUDENTLIST_H_
#include"student.h"
#include<stdio.h>
#include<stdbool.h>
/**
*@brief学生列表结构体定义
*
*/
struct_stu_list{

/**@brief链表头指针*/
Stuhead;

/**@brief链表尾指针*/
Stulast;
};
/**@brief学生链表*/
typedefstruct_stu_listsl;
/**@brief指向学生链表的指针*/
typedefstruct_stu_list*SL;

/**
*@brief创建一个初始化的链表
*
*@return指向_stu_list的指针
*@retvalNULL创建失败
*/
SLlist_init();

/**
*@brief从文件创建一个学生列表
*@paramfile_name含有学生信息的文本文件的文件名
*@return返回学生列表
*@retvalNULL创建失败
*/
SLlist_create_file(char*file_name);
/**
*@brief销毁一个学生信息链表
*
*@paramstu_list要销毁的链表的指针
*/
voidlist_destroy(SLstu_list);

/**
*@brief求学生信息链表的长度
*
*@paramstu_list要求长度的学生信息链表
*
*@return学生信息链表的长度
*@retval-1参数为空
*
*/
intlist_len(SLstu_list);
/**
*@brief判断一个链表是否为空
*
*@paramstu_list要判断是否为空的链表
*
*@retvaltrue为空
*@retvalfalse不为空
*
*/
boollist_is_empty(SLstu_list);
/**
*@brief在链表后追加一个元素
*
*@paramstu_list要追加元素的链表
*@paramstu要追加的元素
*@return返回的元素的指针
*@retvalNULL追加失败
*/
Stulist_append(SLstu_list,Stustu);
/**
*@brief根据学生的学号删除一个学生的信息
*@paramstu_list保存学生信息的链表
*@paramstu_id要删除的学生的学号
*@return返回被删除的学生
*@retvalNULL删除失败
*/
Stulist_delete(SLstu_list,intstu_id);

/**
*@brief输出一个链表的内容
*如果链表为空或参数为NULl,则没有任何输出
*
*@paramstu_list要打印的链表
*/
voidlist_print(SLstu_list);

doublelist_score_sum(SLstu_list);
doublelist_score_avg(SLstu_list);

/**
*@brief根据学生号查的一个学生对象
*
*@paramstu_list保存学生信息的链表
*@paramstu_id要查的的学生的学号
*@paramstu传出查询的学生
*@return查找结果
*@retval-1链表为空
*@retval1查询成功
*@retval0没有查到
*/
intlist_search_id(SLstu_list,intstu_id,Stustu);

/**
*@brief排序链表
*使用选择排序法
*
*@paramstu_list要排序的学生链表
*/
voidlist_sort_avg(SLstu_list);
/**
*@brief把一个学生信息链表写入到当前目录中的一个TXT文本文件
*默认文件名为:student.txt\n
*根据排序的结果,从1开始对学生信息的stu_score_grade字段赋值
*@paramstu_list要写入到文件的学生链表
*@paramfile_name械写入到的文件名
*@return写入到文件中的链表的指针
*/
FILE*list_save_txt(SLstu_list,char*file_name);
/**
*@brief列出平均分高于60的学生的信息
*@paramstu_list学生信息链表
*@return分数高于60分的学生信息链表
*@note返回一个链表的功能还未实现
*/
SLlist_pass(SLstu_list);
#endif/*STUDENTLIST_H_*/


studentList.c//学生列表操作实现

#include"studentList.h"
#include"student.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

/**
*@brief创建一个初始化的链表
*
*@return指向_stu_list的指针
*@retvalNULL创建失败
*/
SLlist_init(){
SLstu_list=(SL)malloc(sizeof(sl));
if(NULL==stu_list){
printf("list_init..动态分配内存失败");
exit(-1);
}
stu_list->head=stu_create(0,"",0.0,0.0);
stu_list->last=stu_create(0,0.0);
stu_list->head->prev=NULL;
stu_list->head->next=stu_list->last;
stu_list->last->prev=stu_list->head;
stu_list->last->next=NULL;
returnstu_list;
}
/**
*@brief从文件创建一个学生列表
*@paramfile_name含有学生信息的文本文件的文件名
*@return返回学生列表
*@retvalNULL创建失败
*/
SLlist_create_file(char*file_name){
FILE*stu_file=fopen(file_name,"r");
if(NULL==stu_file){
returnNULL;
}
SLstu_list=list_init();
intstu_id=0;
charstu_name[10];
doublestu_math=0.0;
doublestu_english=0.0;
doublestu_computer=0.0;
while(EOF
!=fscanf(stu_file,"%d\t%s\t%lf\t%lf\t%lf",&stu_id,stu_name,&stu_math,&stu_english,&stu_computer)){
Stustu=stu_create(stu_id,stu_math,stu_english,stu_computer);
//stu_print(stu);
list_append(stu_list,stu);
}
returnstu_list;
}

/**
*@brief销毁一个学生信息链表
*
*@paramstu_list要销毁的链表的指针
*/
voidlist_destroy(SLstu_list){
if(NULL==stu_list){
return;
}
if(list_is_empty(stu_list)){
free(stu_list);
}
Stutmp=stu_list->head->next;
while(tmp!=stu_list->last){
Stuf=tmp;
tmp->prev->next=tmp->next;
tmp->next->prev=tmp->prev;
tmp=f->next;
free(f);
}
free(stu_list);
}

/**
*@brief求学生信息链表的长度
*
*@paramstu_list要求长度的学生信息链表
*
*@return学生信息链表的长度
*@retval-1参数为空
*
*/
intlist_len(SLstu_list){
if(NULL==stu_list){
return-1;
}
intlen=0;
if(list_is_empty(stu_list)){
len=0;
}
Stutmp=stu_list->head->next;
while(tmp!=stu_list->last){
len++;
tmp=tmp->next;
}
returnlen;
}

/**
*@brief判断一个链表是否为空
*
*@paramstu_list要判断是否为空的链表
*
*@retvaltrue为空
*@retvalfalse不为空
*/
boollist_is_empty(SLstu_list){
boolflags=false;
if(stu_list->head->next==stu_list->last){
flags=true;
}
returnflags;
}

/**
*@brief在链表后追加一个元素
*
*@paramstu_list要追加元素的链表
*@paramstu要追加的元素
*@return返回的元素的指针
*@retvalNULL追加失败
*/
Stulist_append(SLstu_list,Stustu){
if(NULL==stu){
returnNULL;
}
stu_list->last->prev->next=stu;
stu->prev=stu_list->last->prev;
stu->next=stu_list->last;
stu_list->last->prev=stu;
returnstu;
}
/**
*@brief根据学生的学号删除一个学生的信息
*@paramstu_list保存学生信息的链表
*@paramstu_id要删除的学生的学号
*@return返回被删除的学生
*@retvalNULL删除失败
*/
Stulist_delete(SLstu_list,intstu_id){
if(NULL==stu_list){
returnNULL;
}
intlen=list_len(stu_list);
if(len<0){
returnNULL;
}
Stustu=NULL;
list_search_id(stu_list,stu_id,stu);
stu->next->prev=stu->prev;
stu->prev->next=stu->next;
free(stu);
returnNULL;
}

/**
*@brief输出一个链表的内容
*如果链表为空或参数为NULl,则没有任何输出
*
*@paramstu_list要打印的链表
*/
voidlist_print(SLstu_list){
if(list_is_empty(stu_list)){
return;
}
print_title();
Stutmp=stu_list->head->next;
while(tmp!=stu_list->last){
stu_print(tmp);
tmp=tmp->next;
}
}
doublelist_score_sum(SLstu_list){
doublesum=0.0;
Stutmp=stu_list->head->next;
while(tmp!=stu_list->last){
sum+=tmp->stu_score_math+tmp->stu_score_english
+tmp->stu_score_computer;
tmp=tmp->next;
}
returnsum;
}
doublelist_score_avg(SLstu_list){
returnlist_score_sum(stu_list)/list_len(stu_list);
}
intlist_search_id(SLstu_list,Stustu){
if(list_is_empty(stu_list)){
return-1;
}
Stutmp=stu_list->head->next;
//inti=1;
//intlen=list_len(stu_list);
while(tmp!=stu_list->last){
if(tmp->stu_id==stu_id){
break;
}
tmp=tmp->next;
}
if(tmp==stu_list->last){
tmp=NULL;
return0;
}
stu->stu_id=tmp->stu_id;
strcpy(stu->stu_name,tmp->stu_name);
stu->stu_score_math=tmp->stu_score_math;
stu->stu_score_english=tmp->stu_score_english;
stu->stu_score_computer=tmp->stu_score_computer;

return1;
}
voidlist_sort_avg(SLstu_list){
if(list_is_empty(stu_list)||1==list_len(stu_list)){
return;
}
Stustu=stu_list->head->next;
Stustu_next=stu->next;
Stuend=stu_list->last->prev;
while(stu!=end){
//stu_print(stu);
stu_next=stu->next;
while(stu_next!=end->next){
if(stu->stu_score_avg<stu_next->stu_score_avg){
stu_swap(stu,stu_next);
}
stu_next=stu_next->next;
}
stu=stu->next;
stu_next=stu_next->next;
}
stu=stu_list->head->next;
intgrade=1;
while(stu!=stu_list->last){
stu->stu_score_grade=grade;
grade++;
stu=stu->next;
}
}
FILE*list_save_txt(SLstu_list,char*file_name){
if(list_is_empty(stu_list)){
returnNULL;
}
FILE*fp=NULL;
if(NULL==(fp=fopen(file_name,"w"))){
printf("创建!");
exit(-1);
}
Stustu=stu_list->head->next;
while(stu!=stu_list->last){
charstu_info[1024];
sprintf(stu_info,"%d\t%s\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%d\n",stu->stu_id,stu->stu_name,stu->stu_score_math,stu->stu_score_english,stu->stu_score_computer,stu->stu_score_sum,stu->stu_score_avg,stu->stu_score_grade);
//puts(stu_info);
fputs(stu_info,fp);
stu=stu->next;
}
if(0!=fclose(fp)){
puts("关闭文件失败!");
exit(-1);
}
returnNULL;
}
SLlist_pass(SLstu_list){
if(list_is_empty(stu_list)){
returnNULL;
}
Stustu=stu_list->head->next;
while(stu!=stu_list->last){
if(stu->stu_score_avg>=60){
stu_print(stu);
}
stu=stu->next;
}
returnNULL;
}


stuxml.h//xml操作声明

/**@filestuxml.h
*@brief学生管理API
*/

#ifndefSTUMAN_H_
#defineSTUMAN_H_
#include<libxml/tree.h>
#include"studentList.h"




/**@brief创建一个学生信息的XML文件
*
*@paramxml_name该文件的名字,默认为:student.man.xml
*@return
*/
xmlDocPtrman_create_init(char*xml_name);

/**@brief根据一个学生列表创建一个保存学生信息的XML文件
*
*@paramstulist学生列表
*@paramxml_name文件名称
*@return
*/
xmlDocPtrman_create_list(SLstulist,char*xml_name);

/**@brief根据学生创建一个子结点
*
*@paramstu学生
*@return创建的子结点
*@retvalNULL创建失败
*/
xmlNodePtrman_create_node(Stustu);


#endif/*STUMAN_H_*/


stuxml.c//xml操作实现

#include"stuxml.h"
#include"student.h"
#include"studentList.h"
#include<libxml/tree.h>
#include<libxml/parser.h>

/**@brief创建一个学生信息的XML文件
*
*@paramxml_name该文件的名字,默认为:student.man.xml
*@return
*/
xmlDocPtrman_create_init(char*xml_name){
//文档指针
xmlDocPtrdoc=xmlNewDoc(BAD_CAST"1.0");
xmlNodePtrroot=xmlNewNode(NULL,BAD_CAST"stulist");

//设置XML文档的根属性
xmlDocSetRootElement(doc,root);

//保存文档
intnRel=xmlSaveFile(xml_name,doc);
if(nRel!=-1){
printf("一个xml文档被创建,写入%d个字节\n",nRel);
}


returndoc;
}

/**@brief根据一个学生列表创建一个保存学生信息的XML文件
*
*@paramstulist学生列表
*@paramxml_name文件名称
*@return
*/
xmlDocPtrman_create_list(SLstulist,char*xml_name){
if(NULL==stulist){
puts("NULL==stulist");
returnNULL;
}

xmlDocPtrdoc=man_create_init(xml_name);
xmlNodePtrroot=xmlDocGetRootElement(doc);

if(list_is_empty(stulist)){
puts("列表为空");

returndoc;
}

Stustu=stulist->head->next;
while(stu!=stulist->last){

xmlAddChild(root,man_create_node(stu));

stu=stu->next;
}

//保存文档
intnRel=xmlSaveFile(xml_name,doc);
//if(nRel!=-1){
//printf("一个xml文档被创建,写入%d个字节\n",nRel);
//}

//xmlSaveFileEnc(xml_name,doc,"UTF-8");
nRel=xmlSaveFormatFileEnc(xml_name,"UTF-8",1);
printf("一个xml文档被创建,写入%d个字节\n",nRel);

xmlFreeDoc(doc);

returnNULL;
}

/**@brief根据学生创建一个子结点
*
*@paramstu学生
*@return创建的子结点
*@retvalNULL创建失败
*/
xmlNodePtrman_create_node(Stustu){
if(NULL==stu){
returnNULL;
}
charstr[20];
//创建一个子结点
xmlNodePtrnode=xmlNewNode(NULL,BAD_CAST"student");
//设置id属性
sprintf(str,"%d",stu->stu_id);
xmlNewProp(node,BAD_CAST"id",BAD_CASTstr);

//设置子结点
xmlNewTextChild(node,NULL,BAD_CAST"stuName",BAD_CASTstu->stu_name);

sprintf(str,"%.2lf",stu->stu_score_math);
xmlNewTextChild(node,BAD_CAST"stuMath",BAD_CASTstr);

sprintf(str,stu->stu_score_english);
xmlNewTextChild(node,BAD_CAST"stuEnglish",stu->stu_score_computer);
xmlNewTextChild(node,BAD_CAST"stuComputer",stu->stu_score_grade);
xmlNewTextChild(node,BAD_CAST"stuGrade",BAD_CASTstr);

returnnode;
}


输入的文件文件:以Tab键作为分隔符

1001小代码344556
1002老狼251656
1003行者341377
1004天涯341888
1005散人349956

输出的XML文件:

<?xmlversion="1.0"encoding="UTF-8"?>
<stulist>
<studentid="1001">
<stuName>小代码</stuName>
<stuMath>34.00</stuMath>
<stuEnglish>45.00</stuEnglish>
<stuComputer>56.00</stuComputer>
<stuGrade>-1</stuGrade>
</student>
<studentid="1002">
<stuName>老狼</stuName>
<stuMath>25.00</stuMath>
<stuEnglish>16.00</stuEnglish>
<stuComputer>56.00</stuComputer>
<stuGrade>-1</stuGrade>
</student>
<studentid="1003">
<stuName>行者</stuName>
<stuMath>34.00</stuMath>
<stuEnglish>13.00</stuEnglish>
<stuComputer>77.00</stuComputer>
<stuGrade>-1</stuGrade>
</student>
<studentid="1004">
<stuName>天涯</stuName>
<stuMath>34.00</stuMath>
<stuEnglish>18.00</stuEnglish>
<stuComputer>88.00</stuComputer>
<stuGrade>-1</stuGrade>
</student>
<studentid="1005">
<stuName>散人</stuName>
<stuMath>34.00</stuMath>
<stuEnglish>99.00</stuEnglish>
<stuComputer>56.00</stuComputer>
<stuGrade>-1</stuGrade>
</student>
</stulist>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


php输出xml格式字符串
J2ME Mobile 3D入门教程系列文章之一
XML轻松学习手册
XML入门的常见问题(一)
XML入门的常见问题(三)
XML轻松学习手册(2)XML概念
xml文件介绍及使用
xml编程(一)-xml语法
XML文件结构和基本语法
第2章 包装类
XML入门的常见问题(二)
Java对象的强、软、弱和虚引用
JS解析XML文件和XML字符串详解
java中枚举的详细使用介绍
了解Xml格式
XML入门的常见问题(四)
深入SQLite多线程的使用总结详解
PlayFramework完整实现一个APP(一)
XML和YAML的使用方法
XML轻松学习总节篇