Chinaunix首页 | 论坛 | 博客
  • 博客访问: 304961
  • 博文数量: 68
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 706
  • 用 户 组: 普通用户
  • 注册时间: 2015-08-13 14:58
文章分类

全部博文(68)

文章存档

2021年(4)

2020年(6)

2018年(5)

2017年(13)

2016年(8)

2015年(32)

我的朋友

分类: 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" ?>

<Authentication>
<user>
  <userid>001userid>
  <username>rootusername>
  <password>rootpassword>
  user>
<user>
  <userid>002userid>
  <username>ctuusername>
  <password>ctupassword>
  user>
<right>
  <username>rootusername>
  <password>123password>
  right>
  Authentication>

调试 gcc -o test test.c -I /usr/local/include/libxml2/ -L /usr/local/lib -lxml2 -lz
执行 /test xml文件名.xml

阅读(1535) | 评论(0) | 转发(0) |
0

上一篇:FreeTDS C API

下一篇:linux socket 解析xml

给主人留下些什么吧!~~