Chinaunix首页 | 论坛 | 博客
  • 博客访问: 378756
  • 博文数量: 56
  • 博客积分: 1449
  • 博客等级: 中尉
  • 技术积分: 822
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-08 10:24
文章分类

全部博文(56)

文章存档

2014年(7)

2012年(13)

2011年(10)

2010年(26)

分类: C/C++

2011-03-15 13:12:00

  折腾了好些天的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 






阅读(10876) | 评论(2) | 转发(2) |
给主人留下些什么吧!~~

xiumuzi0032017-06-06 10:18:59

菜鸟过来学一下

ibychance2012-01-08 14:56:39

这段代码写的真好