用C语言中的Expat库解析XML文件

用C语言中的Expat库解析XML文件,c,xml,C,Xml,我搜索了如何使用库解析XML文件,但没有发现对初学者有用的东西 我只想从配置文件中读取三个数字6、7和8 <?xml version="1.0" encoding="UTF-8"?> <Configuration> <board_height> 6 </board_height> <board_width> 7 </board_width> <maximum_highscores> 8 &

我搜索了如何使用库解析XML文件,但没有发现对初学者有用的东西

我只想从配置文件中读取三个数字6、7和8

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <board_height> 6 </board_height>
    <board_width> 7 </board_width>
    <maximum_highscores> 8 </maximum_highscores>    
</Configuration>

6.
7.
8.
是一种流式XML解析器。因此,它将文档分块解析,由您(程序员)来维护状态、监控进度,并在解析时捕获所需的数据,而不是在解析之后

您需要构建三个主要处理程序:

  • XML\u StartElementHandler
  • XML\u EndElementHandler
  • XML\u CharacterDataHandler
  • 您可以在
    expat.h
    中找到这些函数的函数签名。第一个函数在找到起始标记(
    )时调用,第二个函数在找到结束标记(
    )时调用,第三个函数捕获标记之间的文本。这是一种基本但快速的解析技术

    以下是使用Expat 2.1的概念证明:

    #include <expat.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #ifdef XML_LARGE_SIZE
    #if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
    #define XML_FMT_INT_MOD "I64"
    #else
    #define XML_FMT_INT_MOD "ll"
    #endif
    #else
    #define XML_FMT_INT_MOD "l"
    #endif
    
    struct setting {
        const char *key;
        char *value;
    } config[] = {
        {"board_height", NULL}, {"board_width", NULL}, {"maximum_highscores", NULL}
    };
    
    struct setting *current_setting;
    
    int
    key_cmp(void const *ld, void const *rd)
    {
        struct setting const *const l = ld;
        struct setting const *const r = rd;
        return strcmp(l->key, r->key);
    }
    
    void XMLCALL
    handler(void *userData, const XML_Char *s, int len)
    {
        if(len == 0){
            return;
        }
    
        if(!current_setting){
            return;
        }
    
        char *value = malloc((len+1) * sizeof(XML_Char));
        strncpy(value, s, len);
        current_setting->value = value;
    }
    
    static void XMLCALL
    startElement(void *userData, const char *name, const char **atts)
    {
        struct setting key = { .key = name };
        current_setting = bsearch(&key, config, sizeof(config)/sizeof(config[0]), sizeof(config[0]), key_cmp);
    }
    
    static void XMLCALL
    endElement(void *userData, const char *name)
    {
        current_setting = NULL;
    }
    
    int
    main(int argc, char *argv[])
    {
        char buf[BUFSIZ];
    
        XML_Parser parser = XML_ParserCreate(NULL);
    
        int done;
        int depth = 0;
    
        XML_SetUserData(parser, &depth);
        XML_SetElementHandler(parser, startElement, endElement);
        XML_SetCharacterDataHandler(parser, handler);
    
        FILE *fp = fopen("config.xml", "r");
    
        do {
            int len = (int)fread(buf, 1, sizeof(buf), fp);
            done = len < sizeof(buf);
            if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) {
                fprintf(stderr,
                        "%s at line %" XML_FMT_INT_MOD "u\n",
                        XML_ErrorString(XML_GetErrorCode(parser)),
                        XML_GetCurrentLineNumber(parser));
                return 1;
            }
        } while (!done);
    
        XML_ParserFree(parser);
    
        int i;
        for (i = 0; i < (sizeof(config)/sizeof(config[0])); i++) {
            struct setting current = config[i];
            printf("%s: %s\n", current.key, current.value);
            free(current.value);
        }
    
        return 0;
    }
    
    #包括
    #包括
    #包括
    #包括
    #ifdef XML_大尺寸
    #如果已定义(XML使用MSC扩展)&&&MSC版本<1400
    #定义XML_FMT_INT_MOD“I64”
    #否则
    #定义XML_FMT_INT_MOD“ll”
    #恩迪夫
    #否则
    #定义XML_FMT_INT_MOD“l”
    #恩迪夫
    结构设置{
    常量字符*键;
    字符*值;
    }配置[]={
    {“线路板高度”,NULL},{“线路板宽度”,NULL},{“最大线路板高度”,NULL}
    };
    结构设置*当前_设置;
    int
    键(无效常数*ld,无效常数*rd)
    {
    结构设置常量*常量l=ld;
    结构设置常数*常数r=rd;
    返回strcmp(左->键,右->键);
    }
    无效XML调用
    处理程序(void*userData、const XML\u Char*s、int len)
    {
    如果(len==0){
    回来
    }
    如果(!当前_设置){
    回来
    }
    char*value=malloc((len+1)*sizeof(XML_char));
    strncpy(值,s,len);
    当前_设置->值=值;
    }
    静态voidxmlcall
    startElement(无效*用户数据,常量字符*名称,常量字符**附件)
    {
    结构设置键={.key=name};
    当前设置=b搜索(&key,config,sizeof(config)/sizeof(config[0]),sizeof(config[0]),key\u;
    }
    静态voidxmlcall
    endElement(void*userData,const char*name)
    {
    当前_设置=空;
    }
    int
    main(int argc,char*argv[])
    {
    char buf[BUFSIZ];
    XML_Parser=XML_ParserCreate(NULL);
    int完成;
    int深度=0;
    XML_SetUserData(解析器和深度);
    XML_SetElementHandler(解析器、startElement、endElement);
    XML_SetCharacterDataHandler(解析器、处理程序);
    文件*fp=fopen(“config.xml”,“r”);
    做{
    int len=(int)fread(buf,1,sizeof(buf),fp);
    完成=长度
    该程序打开一个文件
    config.xml
    进行读取,设置适当的Expat处理程序,并复制它找到的“value”字符串(假设键是xml标记)

    提供的代码只是一个示例。我不是一个专业的C程序员。

    是一个流式XML解析器。因此,它将文档分块解析,由您(程序员)来维护状态、监控进度,并在解析时捕获所需的数据,而不是在解析之后

    您需要构建三个主要处理程序:

  • XML\u StartElementHandler
  • XML\u EndElementHandler
  • XML\u CharacterDataHandler
  • 您可以在
    expat.h
    中找到这些函数的函数签名。第一个函数在找到起始标记(
    )时调用,第二个函数在找到结束标记(
    )时调用,第三个函数捕获标记之间的文本。这是一种基本但快速的解析技术

    以下是使用Expat 2.1的概念证明:

    #include <expat.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #ifdef XML_LARGE_SIZE
    #if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
    #define XML_FMT_INT_MOD "I64"
    #else
    #define XML_FMT_INT_MOD "ll"
    #endif
    #else
    #define XML_FMT_INT_MOD "l"
    #endif
    
    struct setting {
        const char *key;
        char *value;
    } config[] = {
        {"board_height", NULL}, {"board_width", NULL}, {"maximum_highscores", NULL}
    };
    
    struct setting *current_setting;
    
    int
    key_cmp(void const *ld, void const *rd)
    {
        struct setting const *const l = ld;
        struct setting const *const r = rd;
        return strcmp(l->key, r->key);
    }
    
    void XMLCALL
    handler(void *userData, const XML_Char *s, int len)
    {
        if(len == 0){
            return;
        }
    
        if(!current_setting){
            return;
        }
    
        char *value = malloc((len+1) * sizeof(XML_Char));
        strncpy(value, s, len);
        current_setting->value = value;
    }
    
    static void XMLCALL
    startElement(void *userData, const char *name, const char **atts)
    {
        struct setting key = { .key = name };
        current_setting = bsearch(&key, config, sizeof(config)/sizeof(config[0]), sizeof(config[0]), key_cmp);
    }
    
    static void XMLCALL
    endElement(void *userData, const char *name)
    {
        current_setting = NULL;
    }
    
    int
    main(int argc, char *argv[])
    {
        char buf[BUFSIZ];
    
        XML_Parser parser = XML_ParserCreate(NULL);
    
        int done;
        int depth = 0;
    
        XML_SetUserData(parser, &depth);
        XML_SetElementHandler(parser, startElement, endElement);
        XML_SetCharacterDataHandler(parser, handler);
    
        FILE *fp = fopen("config.xml", "r");
    
        do {
            int len = (int)fread(buf, 1, sizeof(buf), fp);
            done = len < sizeof(buf);
            if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) {
                fprintf(stderr,
                        "%s at line %" XML_FMT_INT_MOD "u\n",
                        XML_ErrorString(XML_GetErrorCode(parser)),
                        XML_GetCurrentLineNumber(parser));
                return 1;
            }
        } while (!done);
    
        XML_ParserFree(parser);
    
        int i;
        for (i = 0; i < (sizeof(config)/sizeof(config[0])); i++) {
            struct setting current = config[i];
            printf("%s: %s\n", current.key, current.value);
            free(current.value);
        }
    
        return 0;
    }
    
    #包括
    #包括
    #包括
    #包括
    #ifdef XML_大尺寸
    #如果已定义(XML使用MSC扩展)&&&MSC版本<1400
    #定义XML_FMT_INT_MOD“I64”
    #否则
    #定义XML_FMT_INT_MOD“ll”
    #恩迪夫
    #否则
    #定义XML_FMT_INT_MOD“l”
    #恩迪夫
    结构设置{
    常量字符*键;
    字符*值;
    }配置[]={
    {“线路板高度”,NULL},{“线路板宽度”,NULL},{“最大线路板高度”,NULL}
    };
    结构设置*当前_设置;
    int
    键(无效常数*ld,无效常数*rd)
    {
    结构设置常量*常量l=ld;
    结构设置常数*常数r=rd;
    返回strcmp(左->键,右->键);
    }
    无效XML调用
    处理程序(void*userData、const XML\u Char*s、int len)
    {
    如果(len==0){
    回来
    }
    如果(!当前_设置){
    回来
    }
    char*value=malloc((len+1)*sizeof(XML_char));
    strncpy(值,s,len);
    当前_设置->值=值;
    }
    静态voidxmlcall
    startElement(无效*用户数据,常量字符*名称,常量字符**附件)
    {
    结构设置键={.key=name};
    当前设置=b搜索(&key,config,sizeof(config)/sizeof(config[0]),sizeof(config[0]),key\u;
    }
    静态voidxmlcall
    endElement(void*userData,const char*name)
    {
    当前_设置=空;
    }
    int
    main(int argc,char*argv[])
    {
    char buf[BUFSIZ];
    XML_Parser=XML_ParserCreate(NULL);
    int完成;
    int深度=0;
    XML_SetUserData(解析器和深度);
    XML_SetElementHandler(解析器、startElement、endElement);
    XML_SetCharacterDataHandler(解析器、处理程序);
    文件*fp=fopen(“config.xml”,“r”);
    做{
    int len=(int)fread(buf,1,sizeof(buf),fp);
    完成=长度