ITPub博客

首页 > 应用开发 > > 用C语言解析XML配置文件,使用libxml2动态连接库

用C语言解析XML配置文件,使用libxml2动态连接库

作者:蚂蚁没问题 时间:2019-09-03 14:28:55 0 删除 编辑

折腾了好些天的XML.以及LIBXML2. XML对我来说完全只是听说过而没有看过...还好看了几天效果还不错.

基本的还是懂.今天分配了一个小任务.解析一个XML配置文件,并建立C结构.

XML配置文件如下:



 

 service_1

 eth0

 192.168.8.201

 5

 10

 

 10.0.0.1

 10.0.0.2

 10.0.0.3

 

 

 

 service_2

 eth1

 192.168.8.202

 5

 10

 

 10.1.0.1

 10.1.0.2

 

 

 

C语言头文件如下:

struct items_service{

    char name[128];

    char mif[128];

    char expip[128];

    unsigned int update_period;

    unsigned int sample_number;

    struct media_servers_{

        struct in_addr *ip;

        unsigned int nip;

    }media_servers;

    struct items_service *next;

};

struct items{

    char config[FILENAME_MAX];

    struct items_service *head;

};

OK. 完成这项任务我分为了两个部分.一个部分是负责用XPATH来获取节点集并返回给调用着. 第二部分是使用

这个返回的节点集来初始化字段.这样划分我觉得比较好....

第一部分代码如下:

parse_conf.h 声明和对外接口.

#ifndef _PARSE_CONF_H_

#define _PARSE_CONF_H_

#include 

#include 

#include 

#include 

void xml_parse_conf_init(const char *uri);

xmlNodeSetPtr xml_get_nodeSet(const xmlChar *XPathExpr);

void xml_parse_conf_done(void);

#endif

实现部分: parse_conf.c

#include 

#include 

#include "parse_conf.h"

static xmlDocPtr doc;

static xmlXPathContextPtr XPathCtx;

static xmlXPathObjectPtr XPathObj;

void xml_parse_conf_init(const char *uri)

{

doc = NULL;

XPathCtx = NULL;

xmlInitParser();

doc = xmlParseFile(uri);

if (NULL == doc) {

fprintf(stderr, "Failed to parse %s\n", uri);

exit(-1);

}

 

XPathCtx = xmlXPathNewContext(doc);

if (NULL == XPathCtx) {

fprintf(stderr, "Failed to create XPath context!\n");

exit(-1);

}

}

xmlNodeSetPtr xml_get_nodeSet(const xmlChar *XPathExpr)

{

XPathObj = NULL;

xmlNodeSetPtr nodeSet = NULL;

if (NULL == XPathExpr)

return NULL;

 

XPathObj = xmlXPathEvalExpression(XPathExpr, XPathCtx);

if (NULL == XPathObj) {

fprintf(stderr, "cannot Evaluate the XPath Expression:%s\n",

XPathExpr);

return NULL;

}

nodeSet = XPathObj->nodesetval;

/* 

*just return it.don't bother to check it, 

*let the caller handle it.

*/

return nodeSet;

}

void xml_parse_conf_done(void)

{

if (NULL != XPathObj)

xmlXPathFreeObject(XPathObj);

if (NULL != XPathCtx)

xmlXPathFreeContext(XPathCtx);

if (NULL != doc)

xmlFreeDoc(doc);

}

第二部分的代码如下: build_from_conf.c

#include 

#include 

#include 

#include 

#include 

#include 

#include "parse_conf.h"

#include "def.h"

#define USE_TEST

const char *XML_CONFIGURATION_PATH = "conf.xml";

const char *SERVICE_XPATH = "/conf/service";

const char *NAME_XPATH = "/conf/service/name";

const char *MONITOR_INTERFACE_XPATH = "/conf/service/monitor_interface";

const char *EXPROBE_IP_XPATH = "/conf/service/exprobe_ip";

const char *UPDATE_PERIOD_XPATH = "/conf/service/update_period";

const char *SAMPLE_NUMBER_XPATH = "/conf/service/sample_number";

const char *MEDIA_SERVERS_XPATH = "/conf/service/media_servers";

const char *IP_XPATH = "/conf/service/media_servers/ip";

/*

* allocate memory for all the items appeared in the xml configuration.

*/

static struct items_service *build_struct_init(void)

{

struct items_service *item = NULL;

struct items_service *head = NULL;

struct items_service *next = NULL;

xmlNodeSetPtr nodeSet = NULL;

int i;

 

nodeSet = xml_get_nodeSet(SERVICE_XPATH);

if (NULL == nodeSet) {

fprintf(stderr, "Oops, %s have no nodeSet!\n", SERVICE_XPATH);

return NULL;

}

 

for(i = 0; i < nodeSet->nodeNr; i++) {

item = (struct items_service *)malloc(sizeof(struct items_service));

if (NULL == item) {

while (NULL != head) {

next = head->next;

free(head);

head = next;

}

return NULL;

}

memset(item, 0, sizeof(struct items_service));

item->next = NULL;

if (NULL == head) {

head = item;

next = head;

} else {

next->next = item;

}

}

return head;

}

static void build_name(struct items_service *item)

{

xmlNodeSetPtr nodeSet = NULL;

struct items_service *tmp;

const char *string;

int i;

nodeSet = xml_get_nodeSet(NAME_XPATH);

if (NULL == nodeSet)

return;

tmp = item;

for (i = 0; i < nodeSet->nodeNr; i++) {

if (nodeSet->nodeTab[i]->type != XML_ELEMENT_NODE)

continue;

string = xmlNodeGetContent(nodeSet->nodeTab[i]);

strncpy(tmp->name, string, 127);

tmp->name[127] = '\0';

tmp = tmp->next;

if (NULL == tmp)

break;

}

}

static void build_mif(struct items_service *item)

{

xmlNodeSetPtr nodeSet = NULL;

struct items_service *tmp;

const char *string;

int i;

 

nodeSet = xml_get_nodeSet(MONITOR_INTERFACE_XPATH);

if (NULL == nodeSet)

return;

 

tmp = item;

for (i = 0; i < nodeSet->nodeNr; i++) {

if(nodeSet->nodeTab[i]->type != XML_ELEMENT_NODE)

continue;

string = xmlNodeGetContent(nodeSet->nodeTab[i]);

strncpy(tmp->mif, string, 127);

tmp->mif[127] = '\0';

tmp = tmp->next;

if (NULL == tmp)

break;

}

}

static void build_expip(struct items_service *item)

{

xmlNodeSetPtr nodeSet = NULL;

struct items_service *tmp;

const char *string;

int i;

 

nodeSet = xml_get_nodeSet(EXPROBE_IP_XPATH);

if (NULL == nodeSet)

return;

 

tmp = item;

for (i = 0; i < nodeSet->nodeNr; i++) {

if(nodeSet->nodeTab[i]->type != XML_ELEMENT_NODE)

continue;

string = xmlNodeGetContent(nodeSet->nodeTab[i]);

strncpy(tmp->expip, string, 127);

tmp->expip[127] = '\0';

tmp = tmp->next;

if (NULL == tmp)

break;

}

}

static void build_update_period(struct items_service *item)

{

xmlNodeSetPtr nodeSet = NULL;

struct items_service *tmp;

const char *string;

int i;

 

nodeSet = xml_get_nodeSet(UPDATE_PERIOD_XPATH);

if (NULL == nodeSet)

return;

 

tmp = item;

for (i = 0; i < nodeSet->nodeNr; i++) {

if(nodeSet->nodeTab[i]->type != XML_ELEMENT_NODE)

continue;

string = xmlNodeGetContent(nodeSet->nodeTab[i]);

//printf("update: %s\n", string);

tmp->update_period = atoi(string);

tmp = tmp->next;

if (NULL == tmp)

break;

}

}

static void build_sample_number(struct items_service *item)

{

xmlNodeSetPtr nodeSet = NULL;

struct items_service *tmp;

const char *string;

int i;

 

nodeSet = xml_get_nodeSet(SAMPLE_NUMBER_XPATH);

if (NULL == nodeSet)

return;

 

tmp = item;

for (i = 0; i < nodeSet->nodeNr; i++) {

if(nodeSet->nodeTab[i]->type != XML_ELEMENT_NODE)

continue;

string = xmlNodeGetContent(nodeSet->nodeTab[i]);

tmp->sample_number = atoi(string);

tmp = tmp->next;

if (NULL == tmp)

break;

}

}

static void build_media_servers(struct items_service *item)

{

xmlNodeSetPtr nodeSet = NULL;

xmlNodePtr parent = NULL;

xmlNodePtr child = NULL;

struct items_service *tmp;

const char *ip;

int i, j, res;

 

nodeSet = xml_get_nodeSet(MEDIA_SERVERS_XPATH);

if (NULL == nodeSet)

return;

tmp = item;

for (i = 0; i < nodeSet->nodeNr; i++) {

parent = nodeSet->nodeTab[i];

if (NULL == parent)

break;;

child = parent->children;

if (NULL == child)

break;

 

/* count how may ips thers are */

tmp->media_servers.nip = 0;

while (NULL != child) {

if (child->type == XML_ELEMENT_NODE)

tmp->media_servers.nip++;

child = child->next;

}

tmp->media_servers.ip = (struct in_addr *)

malloc(sizeof(struct in_addr) * tmp->media_servers.nip);

if (NULL == tmp->media_servers.ip) {

fprintf(stderr, "Failed to alloc memory for ip.OOM!\n");

break;

}

/* fill the string format ip into in_addr */

child = parent->children;

j = 0;

while(NULL != child) {

if (child->type == XML_ELEMENT_NODE) {

ip = xmlNodeGetContent(child);

res = inet_pton(AF_INET, ip, &tmp->media_servers.ip[j]);

if (res < 0) {

fprintf(stderr,"transforming string ip to in_addr goes wrong...!\n");

j--;

tmp->media_servers.nip--;

}

j++;

}

child = child->next;

}

tmp = tmp->next;

if (NULL == tmp)

break;

}

 

}

 

 

#ifdef USE_TEST

static void dump_struct(struct items_service *item)

{

int i = 1;

int j;

char ip[INET6_ADDRSTRLEN + 1];

printf("dump struct:\n");

while (NULL != item) {

printf("Item %d\n", i);

printf("name:%s   mif:%s   expip:%s  update_period:%d\nsample_number:%d", 

item->name, item->mif, item->expip, item->update_period, item->sample_number);

for (j = 0; j < item->media_servers.nip; j++) {

printf("ip-%d:%s  ", j + 1, inet_ntop(AF_INET, &item->media_servers.ip[j], ip, 

INET6_ADDRSTRLEN));

}

printf("\n");

item= item->next;

i++;

}

}

/*

static void dump_file(struct items_service *item)

{

char ip[1024];

int i, j;

FILE *fp = fopen("abcdefg.txt", "w");

while (NULL != item) {

fprintf(fp, "Item %d\n", i);

fprintf(fp,"name:%s   mif:%s   expip:%s  update_period:%d\nsample_number:%d", 

item->name, item->mif, item->expip, item->update_period, item->sample_number);

for (j = 0; j < item->media_servers.nip; j++) {

fprintf(fp,"ip-%d:%s  ", j + 1, inet_ntop(AF_INET, &item->media_servers.ip[j], ip, 

INET6_ADDRSTRLEN));

}

fprintf(fp, "\n");

item= item->next;

i++;

}

}

*/

#endif

/* build around head. 0 means success, otherwise something goes wrong */

int build_struct(struct items *head)

{

struct items_service *item = head->head;

 

item = build_struct_init();

if (NULL == item) {

fprintf(stderr, "Ooops...build_struct_init returns NULL,may OOM!\n");

return -1;

}

build_name(item);

build_mif(item);

build_expip(item);

build_update_period(item);

build_sample_number(item);

build_media_servers(item);

head->head = item;

#ifdef USE_TEST

dump_struct(item);

#endif

return 0;

}

#ifdef USE_TEST

int main(void)

{

struct items head;

struct items_service *items;

int res;

memset(&head, 0, sizeof(head));

strncpy(head.config, XML_CONFIGURATION_PATH, FILENAME_MAX);

xml_parse_conf_init(head.config);

res = build_struct(&head);

if (res == -1) {

fprintf(stderr, "Build_struct failed!\n");

return -1;

}

xml_parse_conf_done();

return 0;

}

#endif

以上就是全部代码...运行结果如下,当然只是打印到终端.

dump struct:

Item 1

name:service_1   mif:eth0   expip:192.168.8.201  update_period:5

sample_number:10ip-1:10.0.0.1  ip-2:10.0.0.2  ip-3:10.0.0.3 

Item 2

name:service_2   mif:eth1   expip:192.168.8.202  update_period:5

sample_number:10ip-1:10.1.0.1  ip-2:10.1.0.2 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2568/viewspace-3119859/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-08-16

  • 博文量
    107
  • 访问量
    675