全部博文(68)
分类: C/C++
2015-10-22 13:25:58
由于我们的前台使用C语言编写CGI,如果对方提供XML接口给我们传递数据,就必须有解析的程序,这也可能是今后数据接口的最通用的办法。经过研究,正如使用C语言来生成页面一样,显然使用C语言解析XML要比PHP和ASP要麻烦很多。
同其它语言一样,解析的方法一般都是调用现有的解析器,因为这样省时省力。PHP4是内置的EXPAT,PHP5是内置的LIBXML2,WIN平台可以
调用MSXML。FREEBSD上使用C语言,最流行的就是调用EXPAT和LIBXML2,由于PHP基于某些原因放弃了EXPAT,所以我主要试用了
LIBXML2。
LIBXML2主页是
安装过程:(需要ROOT权限)
gunzip -c libxml2-2.6.22.tar.gz | tar xvf -
cd libxml2-2.6.22
./configure
make
su
make install
exit
安装完成后就可以使用简单的代码解析XML文件,包括本地和远程的文件,但是在编码上有一些问题。LIBXML默认只支持UTF-8的编码,无论输入输出
都是UTF-8,所以如果你解析完一个XML得到的结果都是UTF-8的,如果需要输出GB2312或者其它编码,需要ICONV来做转码(生成
UTF-8编码的文件也可以用它做)。
ICONV的安装过程和LIBXML2一样。
//test.c
#include
#include
#include
#include
#include
#include
//
//
static char s_strBufOut[1024];
char *d_ConvertCharset(char *cpEncodeFrom, char *cpEncodeTo, const
char *cpInput)
{
char *cpOut;
size_t iInputLen, iOutLen, iReturn;
iconv_t c_pt;
if ((c_pt = iconv_open(cpEncodeTo, cpEncodeFrom))
== (iconv_t)-2)
{
printf("iconv_open failed!\n");
return
NULL;
}
iconv(c_pt, NULL, NULL, NULL, NULL);
iInputLen = strlen(cpInput) + 1;
iOutLen = 1024;
cpOut = s_strBufOut;
iReturn = iconv(c_pt, &cpInput,
&iInputLen, &cpOut,
&iOutLen);
if (iReturn == -1)
{
return
NULL;
}
iconv_close(c_pt);
return s_strBufOut;
}
//输出每一项的内容,使用GB2312编码输出
void parseItem (xmlDocPtr doc, xmlNodePtr cur)
{
struct user
{
char
id[20];
char
name[64];
char
password[64];
};
struct user user[2];
xmlChar *key;
cur =
cur->xmlChildrenNode;
while (cur != NULL)
{
int i;
for(i=0;i<2;i++)
{
if ((!xmlStrcmp(cur->name, (const xmlChar
*)"userid")))
{
key = xmlNodeListGetString(doc,
cur->xmlChildrenNode, 1);
//
printf("userid: %s\n", d_ConvertCharset("utf-8", "gb2312", (char
*)key));
char *p = d_ConvertCharset("utf-8","gb2312",(char *)key);
memcpy(user[i].id,p,strlen (p)+1);
xmlFree(key);
}
else if((!xmlStrcmp(cur->name, (const xmlChar
*)"username")))
{
key = xmlNodeListGetString(doc,
cur->xmlChildrenNode, 1);
//
printf("user name: %s\n", d_ConvertCharset("utf-8", "gb2312", (char
*)key));
char *p = d_ConvertCharset("utf-8","gb2312",(char *)key);
memcpy(user[i].name,p,strlen (p)+1);
//
printf("name= %s\n",user1.name);
//
printf("id= %s\n",user1.id);
xmlFree(key);
}
else if ((!xmlStrcmp(cur->name, (const xmlChar
*)"password")))
{
key = xmlNodeListGetString(doc,
cur->xmlChildrenNode, 1);
//
printf("password: %s\n", d_ConvertCharset("utf-8", "gb2312", (char
*)key));
char *p = d_ConvertCharset("utf-8","gb2312",(char *)key);
memcpy(user[i].password,p,strlen(p)+1);
//
printf("id= %s\n",user1.id);
//
printf("name= %s\n",user1.name);
//
printf("passord= %s\n",user1.password);
//
xmlFree(key);
}
}
cur =
cur->next;
}
int j;
for(j=0;j<2;j++)
{
printf("结构体信息:\n");
printf("id:%s name:%s
password:%s\n",user[j].id,user[j].name,user[j].password);
}
return;
}
void parseDoc(char *docname)
{
xmlDocPtr doc; //解析树
xmlNodePtr cur; //当前节点
doc = xmlParseFile(docname);
if (doc == NULL )
{
fprintf(stderr,"Document not parsed successfully. \n");
return;
}
//得到根节点
cur = xmlDocGetRootElement(doc);
if (cur == NULL)
{
fprintf(stderr,"empty document\n");
xmlFreeDoc(doc);
return;
}
//判断根节点是不是mp3
if (xmlStrcmp(cur->name, (const
xmlChar *) "Authentication"))
{
fprintf(stderr,"document of the wrong type, root node !=
Authentication");
xmlFreeDoc(doc);
return;
}
//得到当前节点的第一个子节点,即第一个ITEM
cur = cur->xmlChildrenNode;
while (cur != NULL)
{
if
((!xmlStrcmp(cur->name, (const xmlChar
*)"user")))
{
//输出每个ITEM
printf("用户信息\n");
parseItem (doc, cur);
printf("heeell\n");
}
else
if((!xmlStrcmp(cur->name,(const xmlChar
*)"right")))
{
printf("权限信息\n");
struct role
{
char
name[64];
char
password[64];
};
struct role role1;
xmlChar *key;
cur = cur->xmlChildrenNode;
while(cur !=NULL)
{
if((!xmlStrcmp(cur->name,(const xmlChar
*)"username")))
{
key = xmlNodeListGetString(doc,
cur->xmlChildrenNode,1);
printf("username: %s\n",d_ConvertCharset("utf-8","gb2312",(char
*)key));
char* p = d_ConvertCharset("utf-8","gb2312",(char *)key);
memcpy(role1.name, p, strlen (p) + 1);
xmlFree(key);
}
else if((!xmlStrcmp(cur->name,(const xmlChar
*)"password")))
{
key =
xmlNodeListGetString(doc,cur->xmlChildrenNode,1);
printf("password: %s\n",d_ConvertCharset("utf-8","gb2312",(char
*)key));
char* p = d_ConvertCharset("utf-8","gb2312",(char *)key);
memcpy(role1.password, p, strlen (p) + 1);
}
cur = cur->next;
}
return;
}
cur =
cur->next;
}
xmlFreeDoc(doc);
return;
}
//入参可以是一个文件,也可以是一个URL,要求必须是UTF-8编码
int main(int argc, char **argv)
{
char *docname;
if (argc <= 1)
{
printf("Usage: %s docname\n", argv[0]);
return(0);
}
docname = argv[1];
parseDoc (docname);
return 0;
}
xml文件
xml version="1.0" encoding="UTF-8" ?>
调试 gcc -o test test.c -I
/usr/local/include/libxml2/ -L /usr/local/lib -lxml2 -lz
执行 /test xml文件名.xml