写了一个东西,由于需要完善他希望大家提意见,提者有分

xiezhenghai 2008-04-01 09:53:05
/************************************************************
* *
* --------------------{XML解析器}---------------------- *
* *
* 目的:在c语言环境下实现便捷的配置文件以改善系统结构 *
* *
* *
* 描述:解析版本为1 .0, 字符集为GB2312的XML文件(可能我对他理解有误) *
* 提供功能函数: *
* OpenXML {打开一个XML文件} *
* GetChild {获取子结点} *
* ChildsCount {子结点个数} *
* XMLAttribute {获取结点的详细信息} *
* CloseXML {关闭XML文件} *
* *
* *
* 希望:目前此该段代码可能存在不少的BUG,代码相对拙劣功能也少 *
* 希望能得到改进的意见或者建议此代码优化。 *
* *
************************************************************/
#include <stdio.h>
#include <string.h>
#include <malloc.h>


#define VERSION "version=\"1.0\"" //版本号
#define ENCODING "encoding=\"GB2312\"" //字符集
#define HAVE_CHILD 1
#define NONE_CHILD 0

/************************************************
函 数 名:trim
功 能:过滤字符串左边的空格
入口参数:char *string {被过滤的字符串}
出口参数:无
返 回 值:过滤完的字符串
*************************************************/
char *trim(char *string)
{
while(*string == 32)
string++;
return string;
}

/************************************************
函 数 名:posstr
功 能:在母字符串中查找子字符串
入口参数:char *substr {子字符串}
const char *sourcestr{母字符串}
出口参数:无
返 回 值:成功返回子串在母串中的起始地址
失败返回NULL
*************************************************/
char *posstr(char *substr, const char *sourcestr)
{
char *pos, *subhead=substr;

while(*sourcestr!='\0')
{
pos = (char *)sourcestr;
while(*sourcestr++ == *substr++)
if(*substr=='\0') return pos;
if(substr != subhead) substr=subhead;
}
return NULL;
}

/************************************************
函 数 名:copyfrom
功 能:在母字符串中拷贝两个特定字符间的字符串
入口参数:char startPos {起始字符}
char endPos {结束字符}
char *sourcestr{母字符串}
出口参数:无
返 回 值:成功返回两个特定字符间的字符串
失败返回NULL
局 限:成功返回的字符串长度不能超过1024字节
*************************************************/
char *copyfrom(char startPos, char endPos, char *sourcestr)
{
int index=0;
char buf[1024];
char *pos1, *pos2;

memset(buf, 0, sizeof(buf));
sourcestr = trim(sourcestr);
pos1 = strchr(sourcestr, startPos);
pos2 = strchr(sourcestr, endPos);
if(pos1==NULL || pos2==NULL)
return NULL;
while(++pos1 != pos2) buf[index++] = *pos1;

return buf;
}

...全文
114 点赞 收藏 9
写回复
9 条回复
wpalhm 2008年04月04日
up!
回复 点赞
xiezhenghai 2008年04月04日
有BUG怎么没人提


自己更新!
回复 点赞
wuyu637 2008年04月01日
另外tinyxml是c++的,
你写的是c的。。


:)
回复 点赞
wuyu637 2008年04月01日
其实你能写出来就很不错了,我只是在灌水。。。不过你写之前应该写了解一下有什么可以
用的东西了。
不要重复制造轮子嘛。。。


最后还是要赞一下。。。
up....
回复 点赞
lala_benben 2008年04月01日
。。。LZ好想法 XML配置文件 确实很好用
回复 点赞
ryfdizuo 2008年04月01日
up
回复 点赞
xiezhenghai 2008年04月01日
我并不知道什么才是真正的XML解析器,
一直以来都是在做上层应用软件,觉得用xml做配置文件很好用
可以改善很多结构,之前由于是用delphi语言做开发

由于想转c就拿来练练手, 但是c语言功底薄弱,所以想请教大家一下
回复 点赞
wuyu637 2008年04月01日
问题1,听说过tinyxml,是一个很轻量级的xml解析模块
你的和他的有什么区别?

问题2,你会给我多少分?
回复 点赞
xiezhenghai 2008年04月01日
接上

/************************************************
XML结点结构体
*************************************************/
struct XMLNode{
char Head[1024]; //记录结点头的信息
char NodeName[100]; //结点名
int ChildState; //是否有子结点
int ChildCount; //子结点个数
struct XMLNode *FirstChild; //第一个子结点
struct XMLNode *Father; //指向父结点
struct XMLNode *Next; //下一个结点
};
/************************************************
全局结构体指针
*************************************************/
struct XMLNode *Current,*Father,*Root,*NewNode;

/************************************************
函 数 名:initNewNode
功 能:初始化新生成的结点
入口参数:char *XMLBuf {从文件中读到的一条信息}
int state {结点是否有子结点的状态}
出口参数:无
局 限:如果某结点的内容大于结构体的空间将分配
从堆分配过少的空间
*************************************************/
void initNewNode(char *XMLBuf, int state)
{
//生成结点
NewNode = (struct XMLNode *)malloc(sizeof(struct XMLNode));
//结点头的信息就是从XML文件中读到的整条信息
strcpy(NewNode->Head , XMLBuf);
//结点的名称在字符'<'和'>'之间或者是在第一个'<'与空格之间
if(strchr(copyfrom('<','>',XMLBuf),32) == NULL)
strcpy(NewNode->NodeName, copyfrom('<','>',XMLBuf));
else
strcpy(NewNode->NodeName, copyfrom('<',32, XMLBuf));
//新生成的结点其下一结点为空
NewNode->Next = NULL;
//结点有两中情况一种是存在子结点,另一种是不存在子结点
NewNode->ChildState = state;
//新生成的结点没有子结点,因此子结点个数为0
NewNode->ChildCount = 0;
//为新生成的结点指明其父结点
NewNode->Father = Father;
//新生成的结点没有子结点,因此地一个子结点为空
NewNode->FirstChild = NULL;
}

/************************************************
函 数 名:OpenXML
功 能:打开指定的XML文件
入口参数:char *FileName(XML文件名)
出口参数:无
返 回 值:成功返回根结点的指针
失败返回NULL
局 限:判断不够准确,对空间的分配不够合理
*************************************************/
struct XMLNode *OpenXML(char *FileName)
{
int flag = 0;
char XMLVersion[100];
char XMLBuf[1024];


//判断是否是XML文件,如果不是返回NULL
FILE *f = fopen(FileName,"r");
while(fgets(XMLVersion, sizeof(XMLVersion), f) != NULL)
{
if(posstr("<?",XMLVersion)!=NULL && posstr("?>",XMLVersion)!=NULL)
//判断版本号与字符集是否相对应
if(posstr(VERSION, XMLVersion)!=NULL && posstr(ENCODING, XMLVersion)!=NULL)
{
flag = 1;
break;
}
}
if(flag == 0) return NULL;

//载入根结点
memset(XMLBuf, 0, sizeof(XMLBuf));
while(fgets(XMLBuf, sizeof(XMLBuf), f) != NULL)
{
//以此判断就是根结点,默认根结点是有子结点的
if(strchr(XMLBuf, '<')!=NULL && posstr("<!--",XMLBuf)==NULL)
{
initNewNode(XMLBuf, HAVE_CHILD);

Root = NewNode; Father = NewNode; Current = NewNode;

break;
}

}

/*********************下面开始载入结点*************************/
memset(XMLBuf, 0, sizeof(XMLBuf));
while(fgets(XMLBuf, sizeof(XMLBuf), f) != NULL)
{
//读到的是空行(第一个字符如果是回车键或换行键就认为是空行)
if(*trim(XMLBuf)==10 || *trim(XMLBuf)==13)
{
memset(XMLBuf, 0, sizeof(XMLBuf));
continue;
}
//每读到的信息都应包含字符'<'和字符'>'
if(strchr(XMLBuf, '<')==NULL || strchr(XMLBuf, '>')==NULL)
{
printf("Open XML File:\"%s\" Error!\n", FileName);
return NULL;
}
//把带有"<!--"和"-->"的认为是注释
if(posstr("<!--", XMLBuf)!=NULL && posstr("-->", XMLBuf)!=NULL)
{
memset(XMLBuf, 0, sizeof(XMLBuf));
continue;
}
//带有子结点的结点结束标志
if(posstr("</",XMLBuf)!=NULL)
{
//检查结点结束标志是否正确
if(strcmp(copyfrom('/','>',XMLBuf), Father->NodeName)!=0)
{
printf("Node Configure Error!\n");
return NULL;
}
//退到上一级结点再进行遍历
Current = Current->Father;
if(Father->Father!=NULL)
Father = Father->Father;

memset(XMLBuf, 0, sizeof(XMLBuf));
continue;
}
/******************以下读到的信息是一个结点********************/
//如果生成的结点需要建立新的层次关系则要移动父结点到下一层
if(Current->ChildState==HAVE_CHILD && Current->FirstChild==NULL)
Father = Current;
if(posstr("/>", XMLBuf)==NULL)
initNewNode(XMLBuf, HAVE_CHILD); //该结点存在子结点
else
initNewNode(XMLBuf, NONE_CHILD); //该结点不存在子结点

Current = NewNode; //当前结点移动到新生成的结点处
Father->ChildCount++; //子结点个数递增

//用FirstChild指针或者Next指针记录新生成的结点
if(Father->FirstChild == NULL)
Father->FirstChild = Current;
else
{
NewNode = Father->FirstChild;
while(NewNode->Next!=NULL)
NewNode = NewNode->Next;
NewNode->Next = Current;
}
memset(XMLBuf, 0, sizeof(XMLBuf));
}
fclose(f); //至此XML文件全部读完,应该关闭
return Root; //返回根结点
}

/************************************************
函 数 名:GetChild
功 能:由索引从已知结点中得到相应的子结点
入口参数:struct XMLNode *ANode {指向已知结点的指针}
int Index {子结点的索引}
出口参数:无
返 回 值:成功返回该子结点的指针
失败返回NULL
*************************************************/
struct XMLNode *GetChild(struct XMLNode *ANode, int Index)
{
struct XMLNode *result;
int i;

if(Index >= ANode->ChildCount)
return NULL;
for(i=0; i<=Index; i++)
if(i==0)
result = ANode->FirstChild;
else
result = result->Next;
return result;
}

/************************************************
函 数 名:ChildsCount
功 能:得到已知结点的子结点个数
入口参数:struct XMLNode *ANode {指向已知结点的指针}
出口参数:无
返 回 值:成功返回已知结点的子结点个数
失败返回NULL
*************************************************/
int ChildsCount(struct XMLNode *ANode)
{
return ANode->ChildCount;
}

/************************************************
函 数 名:XMLAttribute
功 能:得到已知结点的叶子信息
入口参数:struct XMLNode *ANode {指向已知结点的指针}
const char *AttributeName{叶子名称}
出口参数:无
返 回 值:成功返回叶子的具体信息
失败返回NULL
局 限:具体信息不能超过100字节
*************************************************/
char *XMLAttribute(struct XMLNode *ANode, const char *AttributeName)
{
char buf[100];
char *pos;
int Index=0;

memset(buf, 0, sizeof(buf));
if((pos=posstr((char *)AttributeName, ANode->Head))==NULL)
return NULL;
//取两个影号之间的数据做为叶子信息
while(*pos++ != '\"') ;

while(*pos != '\"') buf[Index++] = *pos++;

return buf;

}

/************************************************
函 数 名:CloseXML
功 能:关闭XML文件
入口参数:struct XMLNode *Root{指向根结点的指针}
出口参数:无
返 回 值:成功返回0
失败返回-1
*************************************************/
int CloseXML(struct XMLNode *Root)
{
int i;
if(Root==NULL) return -1;

//用递归方式清理堆中分配的内存空间
if(Root->FirstChild==NULL && Root->Next==NULL)
if(strlen(Root->Head)>1024 || strlen(Root->NodeName)>100)
return -1;
else
free(Root);
else
for(i=0; i<Root->ChildCount; i++)
CloseXML(GetChild(Root, i));

return 0;
}
回复 点赞
发动态
发帖子
C语言
创建于2007-09-28

3.2w+

社区成员

24.0w+

社区内容

C语言相关问题讨论
社区公告
暂无公告