zoukankan      html  css  js  c++  java
  • Linux C操作XML文件

    1 简介

    介绍使用C语言操作xml文件。

    使用的开源库:mxml

    mxml源码路径:michaelrsweet/mxml: Tiny XML library. (github.com)

    mxml官网:Mini-XML (msweet.org)

    mxml官方API使用文档:Mini-XML 3.2 API Reference (msweet.org)

    2 安装

    提前说明:mxml编译之后会生成一个静态库和动态链接库。

    首先下载源码压缩包:michaelrsweet/mxml: Tiny XML library. (github.com)

    然后解压之后,按照官方网站的说明进行执行。

    1. 配置编译环境
    ./configure
    

    配置之后,会检查编译环境和配置编译生成的库存放路径,默认放在usr/local中。

    如何需要指定库存放路径,可使用如下命令修改:

    ./configure --prefix=/foo
    

    image-20210507181722591

    2)编译

    直接运行:

    make
    

    image-20210507181828400

    编译完成之后会生成:libmxml.so.1.6、libmxml.a、testmxml(测试代码)。

    3)将mxml安装到系统库中

    执行:

    make install
    

    image-20210507182211455

    安装之后,使用时包含mxml.h即可。

    #include <mxml.h>
    

    在编译程序的使用,可使用 -lmxml 来链接mxml库。

    3 测试

    使用源文件自带的测试案例进行测试。

    编译testmxml.c:

    gcc testmxml.c -lmxml -o testxml	
    

    运行:

    ./testxml test.xml
    

    如果运行出现以下错误,表示没找到libmxml.so.1库。

    image-20210508101409374

    原因:我使用的gcc编译默认使用的是64位的库,也就是/usr/lib64,但是这个库中没有libmxml.so.1

    编译的libmxml.so也是一个64位的库:

    $ file /usr/local/lib/libmxml.so.1.6 
    /usr/local/lib/libmxml.so.1.6: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=4e488abf69cf58184b46a03b881e67a5a92c155f, not stripped
    

    解决方式:建立一个软连接,将安装库的路径链接到系统库中。

    sudo ln -s /usr/local/lib/libmxml.so.1 /usr/lib64/libmxml.so.1
    

    然后重新执行即可。

    image-20210508101604090

    4 部分函数介绍

    首先先介绍一些基本信息。

    4.1 节点

    XML文件中的信息都存放在节点中,节点使用mxml_node_t数据结构进行定义,每个节点有个type成员(定义了节点的类型)、可选数据、父节点(parent 上)、子节点(child 下)、兄弟节点(prev 左和next右)。

    struct _mxml_node_s			/**** An XML node. ****/
    {
      mxml_type_t		type;		/* Node type */
      struct _mxml_node_s	*next;		/* Next node under same parent */
      struct _mxml_node_s	*prev;		/* Previous node under same parent */
      struct _mxml_node_s	*parent;	/* Parent node */
      struct _mxml_node_s	*child;		/* First child node */
      struct _mxml_node_s	*last_child;	/* Last child node */
      _mxml_value_t		value;		/* Node value */
      int			ref_count;	/* Use count */
      void			*user_data;	/* User data */
    };
    

    举例说明,有个xml文件格式如下:

    <?xml version="1.0" encoding="utf-8"?>
    <data>
        <node>val1</node>
        <node>val2</node>
        <node>val3</node>
        <group>
            <node>val4</node>
            <node>val5</node>
            <node>val6</node>
        </group>
        <node>val7</node>
        <node>val8</node>
    </data>
    

    则其在内存中的节点树关系如下:

    ?xml version="1.0" encoding="utf-8"?
      |
    data
      |
    node - node - node - group - node - node
      |      |      |      |       |      |
    val1   val2   val3     |     val7   val8
                           |
                         node - node - node
                           |      |      |
                         val4   val5   val6
    

    ”-“:表示兄弟节点;"|":指向第一个子节点。

    4.1.1 节点类型

    节点类型数据结构定义如下:

    typedef enum mxml_type_e		/**** The XML node type. ****/
    {
      MXML_IGNORE = -1,	/* Ignore/throw away node @since Mini-XML 2.3@ */
      MXML_ELEMENT,	/* XML element with attributes 节点带属性 */
      MXML_INTEGER,	/* Integer value 整型值 */
      MXML_OPAQUE,	/* Opaque string 不透明字符串,不进行字符串分割 */
      MXML_REAL,	/* Real value 实数 */
      MXML_TEXT,	/* Text fragment 文本片段 */
      MXML_CUSTOM	/* Custom data @since Mini-XML 2.1@ */
    } mxml_type_t;
    

    相关函数:获取节点类型。

    mxml_type_t mxmlGetType(mxml_node_t *node);
    

    4.1.2 相关函数

    获取第一个子节点:

    mxml_node_t *mxmlGetFirstChild(mxml_node_t *node);
    

    获取最后一个子节点:

    mxml_node_t *mxmlGetLastChild(mxml_node_t *node);
    

    获取兄弟节点(next右):

    mxml_node_t *mxmlGetNextSibling(mxml_node_t *node);
    

    获取兄弟节点(prev 左):

    mxml_node_t *mxmlGetPrevSibling(mxml_node_t *node);
    

    获取父节点:

    mxml_node_t *mxmlGetParent(mxml_node_t *node);
    

    4.2 创建xml文件并保存

    通过实例简述一下如何创建一个XML文件,并保存它。

    void creat_xml(void)
    {
        mxml_node_t *xml;    /* <?xml ... ?> */
        mxml_node_t *data;   /* <data> */
        mxml_node_t *node;   /* <node> */
        mxml_node_t *group;  /* <group> */
    
        xml = mxmlNewXML("1.0");  //xml头部
    
        data = mxmlNewElement(xml, "data");  //创建节点<data>,父节点为xml
    
            node = mxmlNewElement(data, "node");  //创建节点<note>,父节点为data
            mxmlNewText(node, 0, "val1");  //设置节点<note>的值
            node = mxmlNewElement(data, "node");
            mxmlNewText(node, 0, "val2");
            node = mxmlNewElement(data, "node");
            mxmlNewText(node, 0, "val3");
    
            group = mxmlNewElement(data, "group");
    
                node = mxmlNewElement(group, "node");
                mxmlNewText(node, 0, "val4");
                node = mxmlNewElement(group, "node");
                mxmlNewText(node, 0, "val5");
                node = mxmlNewElement(group, "node");
                mxmlNewText(node, 0, "val6");
    
            node = mxmlNewElement(data, "node");
            mxmlNewText(node, 1, "val7");
            node = mxmlNewElement(data, "node");
            mxmlNewText(node, 1, "val8");   
    
        //save xml
        FILE *fp;
        fp = fopen("filename.xml", "w");
        mxmlSaveFile(xml, stdout, MXML_NO_CALLBACK);
        fclose(fp);
    }
    

    对涉及的函数进行简单介绍:

    /*
     * brife: 新建一个新的XML文档
     * para[in] version: Version number to use
     * return: 新XML文档父节点
    */
    mxml_node_t *mxmlNewXML(const char *version);
    
    /*
     * brife: 创建一个新的节点
     * para[in] parent: 父节点
     * para[in] name: 创建节点名
     * return: 新节点
    */
    mxml_node_t *mxmlNewElement(mxml_node_t *parent, const char *name);
    
    /*
     * brife: 创建一个新的节点文本内容
     * para[in] parent: 父节点
     * para[in] whitespace: 1 = leading whitespace, 0 = no whitespace
     * para[in] string: 文本内容
     * return: 新节点
    */
    mxml_node_t *mxmlNewText(mxml_node_t *parent, int whitespace, const char *string);
    
    /*
     * brife: 保存一个xml树到文件中
     * para[in] note: xml树节点
     * para[in] fp: 写入的文件流指针
     * para[in] cb: 空白回调函数,控制保存文件时插入的"空白"字符
     * return: 成功返回0,出错返回-1
    */
    int mxmlSaveFile(mxml_node_t *node, FILE *fp, mxml_save_cb_t cb);
    
  • 相关阅读:
    使用cygwin中的awk工具进行mysql binlog日志查看[利刃篇]
    设置win版vim启动项[利刃篇]
    php cli模式和浏览器访问下加载php.ini文件的注意事项[架构篇]
    sublime text 3中安装ctags支持函数跳转,安装convertToUtf8支持中文步骤[工具篇]
    在notepad++中使用正则匹配功能(一-龥!-~) 中文[利刃篇]
    微软职位内部推荐-SENIOR SOFTWARE ENGINEER
    微软职位内部推荐-Senior SDE
    微软职位内部推荐-SDEII
    微软职位内部推荐-SOFTWARE ENGINEER II
    微软职位内部推荐-SENIOR SOFTWARE ENGINEER
  • 原文地址:https://www.cnblogs.com/mrlayfolk/p/14743985.html
Copyright © 2011-2022 走看看