`

利用libxml2实现xml文件的创建和解析

阅读更多

我这边的libxlm2是安装centOS6.5时自带的, 其默认的头文件的位置是:

/usr/include/libxml2/libxml/

 文件如下:



 

生成xml文件的代码如下:

/******************************************************
* 练习libxml2库,创建通讯录xml文档,新增一个通讯录, *
* 如果xml文件存在,则添加一个新节点                  *
* 如果xml文件不存在,则新建一个xml文件               *
*                                                    *
* @author: xiao5        @date: 2016/01/04            *
* ****************************************************/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>

#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlmemory.h>

#define PHONE_BOOK_FILE     "phone_book.xml"        // 新增的xml文件的文件名
#define ID_STR_LEN        16            
#define NAME_STR_LEN         32
#define TEL_STR_LEN         16
#define ADDR_STR_LEN         128

//电话通讯录结构体
typedef struct phone_t {
    int id;              //编号
    char name[NAME_STR_LEN];     //姓名
    char tel[TEL_STR_LEN];       //电话
    char address[ADDR_STR_LEN];  //地址
}phone;

//设置通讯录项
static void set_phone_item(phone *phone_item)
{
    assert(phone_item);                     // 设置断言,若程序返回错误则终止程序的执行
    /* 结构体数据初始化 */
    phone_item->id = 10;
    snprintf(phone_item->name, NAME_STR_LEN, "%s", "刘德华");
    snprintf(phone_item->tel, TEL_STR_LEN, "%s", "13018937180");
    snprintf(phone_item->address, ADDR_STR_LEN, "%s", "浙江省杭州市上城区凤起路888号中国人民银行浙江省分行");
}

//创建phone节点
static xmlNodePtr create_phone_node(const phone *phone_item)
{
    assert(phone_item);

    char id[ID_STR_LEN] = {0};
    xmlNodePtr phone_node = NULL;

    phone_node = xmlNewNode(NULL, BAD_CAST"phone");
    if (phone_node == NULL) {
        fprintf(stderr, "Failed to create new node.\n");
        return NULL;
    }
    //设置属性
    snprintf(id, ID_STR_LEN, "%d", phone_item->id);
    xmlNewProp(phone_node, BAD_CAST"id", (xmlChar*)id);

    xmlNewChild(phone_node, NULL, BAD_CAST"name", (xmlChar *)phone_item->name);
    xmlNewChild(phone_node, NULL, BAD_CAST"tel", (xmlChar *)phone_item->tel);
    xmlNewChild(phone_node, NULL, BAD_CAST"address", (xmlChar *)phone_item->address);

    return phone_node;
}

//向根节点中添加一个phone节点
static int add_phone_node_to_root(xmlNodePtr root_node)
{
    xmlNodePtr phone_node = NULL;
    phone *phone_item = NULL;

    //创建一个新的phone
    phone_item = (phone *)malloc(sizeof(phone));
    if (phone_item == NULL) {
        fprintf(stderr, "Failed to malloc memory.\n");
        return -1;
    }
    set_phone_item(phone_item);

    //创建一个phone节点
    phone_node = create_phone_node(phone_item); 
    if (phone_node == NULL) {
        fprintf(stderr, "Failed to create phone node.\n");
        goto FAILED;
    }
    //根节点添加一个子节点
    xmlAddChild(root_node, phone_node);
    free(phone_item);

    return 0;
    FAILED:
    if (phone_item){
        free(phone_item);
    }
    return -1;
}

//创建phone_books
static int create_phone_books(const char *phone_book_file)
{
    assert(phone_book_file);

    xmlDocPtr doc = NULL;
    xmlNodePtr root_node = NULL;

    //创建一个xml 文档
    doc = xmlNewDoc(BAD_CAST"1.0");
    if (doc == NULL) {
        fprintf(stderr, "Failed to new doc.\n");
        return -1;
    }

    //创建根节点
    root_node = xmlNewNode(NULL, BAD_CAST"phone_books");
    if (root_node == NULL) {
        fprintf(stderr, "Failed to new root node.\n");
        goto FAILED;
    }
    //将根节点添加到文档中
    xmlDocSetRootElement(doc, root_node);

    if (add_phone_node_to_root(root_node) != 0) {
        fprintf(stderr, "Failed to add a new phone node.\n");
        goto FAILED;
    }
    //将文档保存到文件中,按照utf-8编码格式保存
    xmlSaveFormatFileEnc(phone_book_file, doc, "UTF-8", 1);
    //xmlSaveFile("test.xml", doc);
    xmlFreeDoc(doc);

    return 0; 
    FAILED:
    if (doc) {
        xmlFreeDoc(doc);
    }

    return -1;
}

static int add_phone_node(const char *phone_book_file)
{
    assert(phone_book_file);

    xmlDocPtr doc = NULL;
    xmlNodePtr root_node = NULL;
    xmlNodePtr phone_node = NULL;
    phone *phone_item = NULL;

    doc = xmlParseFile(phone_book_file);
    if (doc == NULL) {
        fprintf(stderr, "Failed to parser xml file:%s\n", phone_book_file);
        return -1;
    }

    root_node = xmlDocGetRootElement(doc);
    if (root_node == NULL) {
        fprintf(stderr, "Failed to get root node.\n");
        goto FAILED;
    }

    if (add_phone_node_to_root(root_node) != 0) {
        fprintf(stderr, "Failed to add a new phone node.\n");
        goto FAILED;
    }
    //将文档保存到文件中,按照utf-8编码格式保存
    xmlSaveFormatFileEnc(phone_book_file, doc, "UTF-8", 1);
    xmlFreeDoc(doc);

    return 0;
    FAILED:
    if (doc) {
        xmlFreeDoc(doc);
    }

    return -1;
}

int main(int argc, char *argv[])
{
    char *phone_book_file = PHONE_BOOK_FILE;

    if (argc == 2) {
        phone_book_file = argv[1];
    }

    if (access(phone_book_file, F_OK) == 0) {
        //文件存在,添加一个新的phone节点
        add_phone_node(phone_book_file);
    }
    else {
        //文件不存在,创建一个信息的phone book
        create_phone_books(phone_book_file);
    }

    return 0;
}

编译命令:

 

gcc -I /usr/include/libxml2  -L /usr/local/lib -lxml2 1.c -o 1

 

生成的文件的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<phone_books>
  <phone id="10">
    <name>刘德华</name>
    <tel>13018937180</tel>
    <address>浙江省杭州市上城区凤起路888号中国人民银行浙江省分行</address>
  </phone>
</phone_books>

 

解析代码:

/********************************************
 * 调用libxml2库解析xml,提取出电话薄信息   *
 *                                          *
 * @author:xiao5     @date:2016/01/04       *
 * ******************************************/

#include <stdio.h>
#include <assert.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>

#define DEFAULT_XML_FILE "phone_book.xml"

//解析每一个phone,提取出name、tel、address
static int parse_phone(xmlDocPtr doc, xmlNodePtr cur)
{
    assert(doc || cur);
    xmlChar *key;

    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
        //获取name
        if ((!xmlStrcmp(cur->name, (const xmlChar *)"name"))) {
            key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
            printf("name: %s\t", key);
            xmlFree(key);
        }
        //获取tel
        if ((!xmlStrcmp(cur->name, (const xmlChar *)"tel"))) {
            key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
            printf("tel: %s\t", key);
            xmlFree(key);
        }
        //获取address
        if ((!xmlStrcmp(cur->name, (const xmlChar *)"address"))) {
            key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
            printf("address: %s\n", key);
            xmlFree(key);
        }
        cur = cur->next;
    }
    return 0;
}

static int parse_phone_book(const char *file_name)
{
    assert(file_name);

    xmlDocPtr doc;   //xml整个文档的树形结构
    xmlNodePtr cur;  //xml节点
    xmlChar *id;     //phone id

    //获取树形结构
    doc = xmlParseFile(file_name);
    if (doc == NULL) {
        fprintf(stderr, "Failed to parse xml file:%s\n", file_name);
        goto FAILED;
    }

    //获取根节点
    cur = xmlDocGetRootElement(doc);
    if (cur == NULL) {
        fprintf(stderr, "Root is empty.\n");
        goto FAILED;
    }

    if ((xmlStrcmp(cur->name, (const xmlChar *)"phone_books"))) {
        fprintf(stderr, "The root is not phone_books.\n");
        goto FAILED;
    }

    //遍历处理根节点的每一个子节点
    cur = cur->xmlChildrenNode;
    while (cur != NULL) {
    if ((!xmlStrcmp(cur->name, (const xmlChar *)"phone"))) {
        id = xmlGetProp(cur, "id");
        printf("id:%s\t",id);
        parse_phone(doc, cur);
    }
    cur = cur->next;
    }
    xmlFreeDoc(doc);
    return 0;
FAILED:
    if (doc) {
        xmlFreeDoc(doc);
    }
    return -1;
}

int main(int argc, char*argv[])
{
    char *xml_file = DEFAULT_XML_FILE;

    if (argc == 2) {
        xml_file = argv[1];
    }

    if (parse_phone_book(xml_file) != 0) {
        fprintf(stderr, "Failed to parse phone book.\n");
        return -1;
    }

    return 0;
}

 编译命令:

gcc -I /usr/include/libxml2  -L /usr/local/lib -lxml2 2.c -o 2

 

生成的结果如下:

 

 

OK 了!!

  • 大小: 23.9 KB
  • 大小: 9.3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics