利用libxml2解析xml文件

本文简单介绍libxml2的安装及基于C语言从xml文件中解析出相关内容。

参考博客:libxml2的安装及使用_阿卡基YUAN的博客-CSDN博客_libxml2

一、libxml2安装

1、源码安装:

gitee仓库:libxml2: libxml2压缩文件夹

解压

cd libxml2-2.7.4

./configure prefix=指定路径

make

make install

2、shell安装

sudo apt-get install libxml2 
 
sudo apt-get install libxml2-dev

二、数据类型和函数

1、内部字符类型xmlChar

xmlChar是Libxml2中的字符类型,库中所有字符、字符串都是基于这个数据类型,类似char。很多libxml2的函数会返回一个动态分配内存的xmlChar*变量,所以使用这样的函数时要记得手动xmlFreeDoc(读入的文件)删除内存。

2、xmlChar相关函数

xmlMalloc是动态分配内存的函数;xmlFree是配套的释放内存函数;xmlStrcmp是字符串比较函数;xmlGetProp取出其属性值等。

3、文件类型xmlDoc、指针xmlDocPtr

xmlDoc是个struct,保存了一个xml的相关信息,例如文件名、文件类型、子节点等等;xmlDocPtr等于xmlDoc*。xmlReadFile函数读入一个带有某种编码的xml文件,并返回文件指针;细节见libxml2参考册。xmlFreeDoc释放文件指针。特别注意,当你调用xmlFreeDoc时,该文件所有包含的节点内存都被释放。

4、节点类型xmlNode、指针xmlNodePtr(与链表类似

typedef struct _xmlNode xmlNode;
typedef xmlNode *xmlNodePtr;                                                                                           

struct _xmlNode {
    void           *_private;/* application data */
    xmlElementType   type;   /* type number, must be second ! */
    const xmlChar   *name;      /* the name of the node, or the entity */  节点名字:name;
    struct _xmlNode *children; /* parent->childs link */
    struct _xmlNode *last;   /* last child link */
    struct _xmlNode *parent;/* child->parent link */
    struct _xmlNode *next;   /* next sibling link */  
    struct _xmlNode *prev;   /* previous sibling link */
    struct _xmlDoc *doc;/* the containing document */                             节点所属文件:doc;
    /* End of common part */
    xmlNs         *ns;        /* pointer to the associated namespace */
    xmlChar     *content;   /* the content */                                    节点中的文字内容:content;
    struct _xmlAttr *properties;/* properties list */
    xmlNs         *nsDef;     /* namespace definitions on this node */
    void             *psvi;/* for type/PSVI informations */
    unsigned short   line;   /* line number */
    unsigned short   extra; /* extra data for XPath/XSLT */
};

三、解析xml实例

解析一个XML文档,从中取出想要的信息,例如节点中包含的文字,或者某个节点的属性。其流程如下:

1、用xmlReadFile函数读入一个文件,并返回一个文档指针doc。

2、用xmlDocGetRootElement函数得到根节点cur。

3、此时cur->xmlChildrenNode就是根节点的首个儿子节点,该儿子节点的兄弟节点可用next指针进行轮询。

4、轮询所有子节点,用xmlStrcmp与想找的内容作比较,等于0,即找到

5、取出该节点的属性,用xmlGetProp取出其属性值。

6、xmlFreeDoc函数关闭文档指针,并清除本文档中所有节点动态申请的内存。

xml例:apns-full-conf.xml(实际没有这么少内容,我删减了)

<apns version="8">    /* 这是根节点 */

  <apn carrier="AT&amp;T PHONE TEST SIM"    /* 子节点 */
      carrier_id = "1911"                   /* 节点的相关属性 */
      mcc="001"
      mnc="01"
      apn="phone"
      user=""
      password=""
      proxy=""
      port=""
      mmsc="http://mmsc.mobile.att.net"
      mmsproxy="proxy.mobile.att.net"
      mmsport="80"
      type="default,mms,supl,hipri,fota,dun"
      mtu="1410"
  />

  <apn carrier="T-Mobile TEST SIM"
      carrier_id = "1911"
      mcc="001"
      mnc="01"
      apn="phone"
      user=""
      password=""
      proxy=""
      port=""
      type="default,supl,hipri,dun"
      mtu="1440"
  />

  <apn carrier="CTNET"
      carrier_id = "2237"
      mcc="460"
      mnc="03"
      apn="ctnet"
      user="ctnet@mycdma.cn"
      password="vnet.mobi"
      authtype="3"
      server="*"
      proxy=""
      port="80"
      mmsc=""
      mmsproxy=""
      mmsport=""
      type="default,hipri,fota,cbs"
      protocol="IP"
  />

  <apn carrier="CTWAP"
      carrier_id = "2237"
      mcc="460"
      mnc="03"
      apn="ctwap"
      user="ctwap@mycdma.cn"
      password="vnet.mobi"
      authtype="3"
      server="*"
      proxy=""
      port="80"
      mmsc="http://mmsc.vnet.mobi"
      mmsproxy="10.0.0.200"
      mmsport="80"
      type="default,mms,hipri,supl,fota,cbs"
      protocol="IP"
  />

</apns>

 

query_apn.c:(解析出APN)

#include <stdio.h>
#include <string.h>
#include <libxml2/libxml/xmlmemory.h>
#include <libxml2/libxml/parser.h>
#include <libxml/xmlversion.h>
#include <libxml/xmlstring.h>

#define   FILE_NAME  "/home/nbiot/pengjiawei/sms_-modem/apns-full-conf.xml"

void query_apn(char *file_name);

int main(int argc,char **argv)
{
        query_apn(FILE_NAME);

        return 0;
}

void query_apn(char *file_name)
{
        xmlDocPtr       doc;        //文档指针
        xmlNodePtr      cur;        //根节点
        xmlChar         *mcc;       //移动国家代码
        xmlChar         *mnc;       //移动网络代码
        xmlChar         *apn;       //PPP拨号APN

        /*      目标mcc与mnc      */
        char    *qmcc = "460";
        char    *qmnc = "03";

        if( !file_name )
        {
                printf("Invalid input arguments\n");
        }

        doc = xmlReadFile(file_name, "UTF-8", XML_PARSE_RECOVER);  //读入需要解析的xml文件
        if (doc == NULL)
        {
                printf("Failed to read xml file:%s\n", file_name);
                goto cleanup;
        }

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

        if ( xmlStrcmp(cur->name, (const xmlChar *)"apns") )    //判断根节点是否正确,注意强制类型转换
        {
                printf("The root is not apns.\n");
                goto cleanup;
        }

        cur = cur->xmlChildrenNode;     //由根节点指向子节点

        while (cur != NULL)
        {
                if ( xmlStrcmp(cur->name, (const xmlChar *)"apn")==0 )  //现在的cur->name子节点的name,判断name里有没有apn,若有,往下走
                {
                        /*      xmlGetProp取出其属性值      */
                        mcc = xmlGetProp(cur, "mcc");
                        mnc = xmlGetProp(cur, "mnc");

                        if( xmlStrcmp(mcc, (const xmlChar *)qmcc)==0 && xmlStrcmp(mnc, (const xmlChar *)qmnc)==0 )  //若mcc和mnc是460 03同时成立,则获取该子节点APN
                        {
                                apn = xmlGetProp(cur, "apn");
                                printf("mcc:%s mnc:%s apn:%s \n",mcc, mnc, apn);

                                break;
                        }
                }
                cur = cur->next;        //若不满足条件则指向下一个子节点
        }
cleanup:
        if (doc)
        {
                xmlFreeDoc(doc);
        }

}

编译:(安装的源码要记得指定头文件和库的位置)

gcc query_apn.c -o query_apn -I /home/nbiot/pengjiawei/libxml2/include/libxml2 -L /home/nbiot/pengjiawei/libxml2/lib -lxml2

结果:

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值