折腾了好些天的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
阅读(2414) | 评论(0) | 转发(0) |