美文网首页
简单使用expat

简单使用expat

作者: louyang | 来源:发表于2019-06-29 12:35 被阅读0次

    XML不可能比过Json或Yaml的,因为太复杂了。但是有些老旧项目还在使用XML解析器(expat),所以顺便学习了一下。

    实验环境,在CentOS操作系统上安装expat开发库:

    sudo yum install expat-devel
    

    https://libexpat.github.io/doc/getting-started/ 下载

    编译运行:

    gcc elements.c && cat a.xml | ./a.out
    gcc outline.c && cat a.xml | ./a.out
    

    https://www.xml.com/pub/a/1999/09/expat/index.html所说,学会4个expat函数,就可以应付80%的场景,接下来我们来体验一下。

    (1) 创建一个解析器

    XML_Parser parser = XML_ParserCreate(NULL);
    

    (2) 挂钩子函数,处理起始和结束标签

    void startElement(void *userData, const XML_Char *name, const XML_Char **atts) {...}
    void endElement(void *userData, const XML_Char *name) {...}
    
    XML_SetElementHandler(parser, startElement, endElement);
    

    (3) 挂钩子函数,处理内容

    void handle_data(void *data, const char *content, int length) {...}
    XML_SetCharacterDataHandler(parser, handle_data);
    

    (4) 开始解析

    if (XML_Parse(parser, buf, (int)len, done) == XML_STATUS_ERROR) {
    

    举个例子,假设现在有a.xml如下:

    <note>
    <aaa>111</aaa>
    <bbb>222</bbb>
    <ccc>333</ccc>
    <ddd>444</ddd>
    </note>
    

    我们想把它转换成yaml格式,显示在屏幕上,如下:

    note:
        aaa: '111'
        bbb: '222'
        ccc: '333'
        ddd: '444'
    

    代码可以是这样的:

    #include <fstream>
    #include <iostream>
    #include <utility>
    #include <string>
    #include <vector>
    #include <expat.h>
    
    struct node {
        size_t depth {0};
        std::string name {""};
        std::string value {""};
    };
    
    std::vector<node> root;
    node current;
    
    void startElement(void *userData, const XML_Char *name, const XML_Char **atts)
    {
        int *depthPtr = (int *)userData;
        if (current.name.length() != 0)
        {
            root.push_back(current);
        }
        current.name = name;
        current.depth = *depthPtr;
        *depthPtr += 1;
    }
    
    void endElement(void *userData, const XML_Char *name)
    {
        int *depthPtr = (int *)userData;
        if (current.name.length() != 0)
        {
            root.push_back(current);
            current.depth = 0;
            current.name = "";
            current.value = "";
        }
        *depthPtr -= 1;
    }
    
    void handle_data(void *data, const char *content, int length)
    {
         current.value = content;
         current.value.erase(length);
    }
    
    void show_data()
    {
        for (auto e : root)
        {
            std::cout << std::string(e.depth,' ') << e.name << ":" << e.value << std::endl;
        }
    }
    
    int main(int argc, const char *argv[])
    {
        XML_Parser parser = XML_ParserCreate(NULL);
        XML_SetElementHandler(parser, startElement, endElement);
        XML_SetCharacterDataHandler(parser, handle_data);
        int depth = 0;
        XML_SetUserData(parser, &depth);
    
        std::ifstream ifs(argv[1]);
        std::string line;
        while (std::getline(ifs, line))
        {
            XML_Parse(parser, line.c_str(), line.length(), 0);
        }
    
        XML_ParserFree(parser);
        show_data();
        return 0;
    }
    

    运行:

    $ g++ a.c --std=c++11 -lexpat && ./a.out a.xml
    note:
     aaa:111
     bbb:222
     ccc:333
     ddd:444
    

    相关文章

      网友评论

          本文标题:简单使用expat

          本文链接:https://www.haomeiwen.com/subject/mphscctx.html