当前位置:首页 > C > 正文

C语言快速上手expat库(小白也能学会的XML解析教程)

在C语言开发中,处理XML数据是一项常见任务。而expat库是一个轻量级、高效的XML解析器,非常适合嵌入到C项目中。本教程将带你从零开始,一步步学会如何使用C语言 expat库来解析XML文件,即使你是编程新手也能轻松掌握!

什么是expat库?

expat 是一个用C语言编写的开源XML解析器,采用事件驱动(SAX风格)方式工作。它不依赖其他库,体积小、速度快,非常适合资源受限的环境。当你需要在C程序中读取或处理XML格式的数据时,expat是一个极佳的选择。

C语言快速上手expat库(小白也能学会的XML解析教程) C语言 expat库 XML解析 教程 第1张

安装expat库

在大多数Linux发行版中,你可以通过包管理器安装expat:

# Ubuntu/Debiansudo apt-get install libexpat1-dev# CentOS/RHELsudo yum install expat-devel

在Windows下,你可以从expat官网下载预编译库或源码自行编译。

编写第一个expat解析程序

我们以一个简单的XML文件为例:

<?xml version="1.0" encoding="UTF-8"?><bookstore>  <book id="1">    <title>C语言入门</title>    <author>张三</author>  </book>  <book id="2">    <title>XML解析实战</title>    <author>李四</author>  </book></bookstore>

我们的目标是读取每本书的标题和作者。下面是完整的C代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <expat.h>// 全局变量:记录当前是否在 title 或 author 标签内int in_title = 0;int in_author = 0;// 起始标签处理函数void startElement(void *userData, const char *name, const char **atts) {    if (strcmp(name, "title") == 0) {        in_title = 1;    } else if (strcmp(name, "author") == 0) {        in_author = 1;    }}// 结束标签处理函数void endElement(void *userData, const char *name) {    if (strcmp(name, "title") == 0) {        in_title = 0;    } else if (strcmp(name, "author") == 0) {        in_author = 0;    }}// 字符数据处理函数void characterData(void *userData, const XML_Char *s, int len) {    // 分配临时字符串并复制内容    char *data = malloc(len + 1);    strncpy(data, s, len);    data[len] = '\0';    if (in_title) {        printf("书名: %s\n", data);    } else if (in_author) {        printf("作者: %s\n", data);    }    free(data);}int main() {    FILE *fp = fopen("books.xml", "r");    if (!fp) {        perror("无法打开文件");        return 1;    }    // 创建解析器    XML_Parser parser = XML_ParserCreate(NULL);    if (!parser) {        fprintf(stderr, "无法创建解析器\n");        fclose(fp);        return 1;    }    // 设置回调函数    XML_SetElementHandler(parser, startElement, endElement);    XML_SetCharacterDataHandler(parser, characterData);    // 逐块读取并解析    char buffer[1024];    int done;    do {        size_t len = fread(buffer, 1, sizeof(buffer), fp);        done = feof(fp);        if (XML_Parse(parser, buffer, len, done) == XML_STATUS_ERROR) {            fprintf(stderr, "解析错误: %s at line %d\n",                    XML_ErrorString(XML_GetErrorCode(parser)),                    XML_GetCurrentLineNumber(parser));            XML_ParserFree(parser);            fclose(fp);            return 1;        }    } while (!done);    // 清理资源    XML_ParserFree(parser);    fclose(fp);    return 0;}

代码详解

1. 回调函数:expat使用事件驱动模型,你需要提供三个主要回调函数:

  • startElement:遇到起始标签时调用
  • endElement:遇到结束标签时调用
  • characterData:遇到文本内容时调用

2. 状态标记:我们用in_titlein_author两个全局变量来跟踪当前是否处于目标标签内部,这样在characterData中就能判断是否要输出内容。

3. 内存安全:注意characterData中的s指针指向的是expat内部缓冲区,不能直接保存。所以我们复制了一份再使用。

编译与运行

将上面的代码保存为parse_xml.c,XML内容保存为books.xml,然后执行以下命令编译:

gcc -o parse_xml parse_xml.c -lexpat

运行程序:

./parse_xml

你将看到如下输出:

书名: C语言入门作者: 张三书名: XML解析实战作者: 李四

总结

通过本教程,你已经学会了如何使用C语言 expat库进行基本的XML解析。expat虽然简单,但功能强大,适合各种嵌入式或高性能场景。记住关键点:设置回调函数、管理解析状态、正确处理字符数据。希望这篇教程能帮助你在C语言开发中轻松应对XML数据!

关键词回顾:C语言、expat库、XML解析、教程