zoukankan      html  css  js  c++  java
  • linux下使用libxml2实现对xml文件的读取及查询

      由于项目需要,这两天在用C++做XML文件解析的工作。在linux下有个很方便的操作xml文件的库——libxml2,它提供了一套创建和查询xml文件的C语言的接口。这篇博客主要介绍如何使用libxml2读取并解析xml文件。

    下载并安装libxml2

    下载地址:ftp://xmlsoft.org/libxml2/

    下载最新的版本,我下载的是libxml2-2.9.1.tar.gz。下载后将文件解压到合适的位置,进入解压后的目录。

    编译命令非常简单(注意:如果configure文件没有可执行权限,增加可执行权限):

    ./configure
    make
    make install

    此时libxml2相关的头文件应该在/usr/local/include/libxml2目录下,libxml2相关的库文件应该在/usr/local/lib目录下。

    解析XML文档的两种方式

           在使用libxml2进行XML文档的解析时,非常推荐使用XPath语言实现,如果把XML文件看作数据库的话,那么XPath就可被视为sql,我们只要构造一定格式的语句就可查询到相关结果,而在在libxml2中使用Xpath是非常简单的。当然我们也可以直接通过libxml2相关接口从跟节点出发,根据整个xml的父子节点关系定位到相关节点进行查询。下面我将分别对这两种方式进行介绍。

           我们使用下面的xml测试用例:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    
    <bookstore>
    
    <book>
    <title lang="eng">Harry Potter</title>
    <price>29.99</price>
    </book>
    
    <book>
    <title lang="eng">Learning XML</title>
    <price>39.95</price>
    </book>
    
    </bookstore>

    直接使用libxml2接口解析XML文档

    #include <stdio.h>
    #include <stdlib.h>
    #include <libxml/parser.h>
    #include <libxml/tree.h>
    
    
    int main (int argc , char **argv)
    {
    xmlDocPtr pdoc = NULL;
    xmlNodePtr proot = NULL, pcur = NULL;
    /*****************打开xml文档********************/
    xmlKeepBlanksDefault(0);//必须加上,防止程序把元素前后的空白文本符号当作一个node
    pdoc = xmlReadFile ("test.xml", "UTF-8", XML_PARSE_RECOVER);//libxml只能解析UTF-8格式数据
    
    if (pdoc == NULL)
    {
    printf ("error:can't open file!
    ");
    exit (1);
    }
    
    /*****************获取xml文档对象的根节对象********************/
    proot = xmlDocGetRootElement (pdoc);
    
    if (proot == NULL)
    {
    printf("error: file is empty!
    ");
    exit (1);
    }
    
    /*****************查找书店中所有书籍的名称********************/
    pcur = proot->xmlChildrenNode;
    
    while (pcur != NULL)
    {
    //如同标准C中的char类型一样,xmlChar也有动态内存分配,字符串操作等 相关函数。例如xmlMalloc是动态分配内存的函数;xmlFree是配套的释放内存函数;xmlStrcmp是字符串比较函数等。
    //对于char* ch="book", xmlChar* xch=BAD_CAST(ch)或者xmlChar* xch=(const xmlChar *)(ch)
    //对于xmlChar* xch=BAD_CAST("book"),char* ch=(char *)(xch)
    if (!xmlStrcmp(pcur->name, BAD_CAST("book")))
    {
    xmlNodePtr nptr=pcur->xmlChildrenNode;
    while (pcur != NULL)
    {
    if (!xmlStrcmp(nptr->name, BAD_CAST("title")))
    {
    printf("title: %s
    ",((char*)XML_GET_CONTENT(nptr->xmlChildrenNode)));
    break;
    }
    }
    
    }
    pcur = pcur->next;
    }
    
    /*****************释放资源********************/
    xmlFreeDoc (pdoc);
    xmlCleanupParser ();
    xmlMemoryDump ();
    return 0;
    }


      具体流程我已经在代码中详细注释,这里就不单独拿出来解释。


    使用XPath语言解析XML文档

            关于XPath的基础知识,可以访问http://www.w3school.com.cn/xpath/index.asp
    #include <stdio.h>
    #include <stdlib.h>
    #include <libxml/parser.h>
    #include <libxml/tree.h>
    #include <libxml/xpath.h>
    #include <libxml/xpathInternals.h>
    #include <libxml/xmlmemory.h>
    #include <libxml/xpointer.h>
    
    xmlXPathObjectPtr getNodeset(xmlDocPtr pdoc,const xmlChar *xpath)
    {
    xmlXPathContextPtr context=NULL;//XPath上下文指针
    xmlXPathObjectPtr result=NULL; //XPath结果指针
    context = xmlXPathNewContext(pdoc);
    
    if(pdoc==NULL){
    printf("pdoc is NULL
    ");
    return NULL;
    }
    
    if(xpath){
    if (context == NULL) {
    printf("context is NULL
    ");
    return NULL;
    }
    
    result = xmlXPathEvalExpression(xpath, context);
    xmlXPathFreeContext(context); //释放上下文指针
    if (result == NULL) {
    printf("xmlXPathEvalExpression return NULL
    ");
    return NULL;
    }
    
    if (xmlXPathNodeSetIsEmpty(result->nodesetval)) {
    xmlXPathFreeObject(result);
    printf("nodeset is empty
    ");
    return NULL;
    }
    }
    
    return result;
    }
    
    int main (int argc , char **argv){
    xmlDocPtr pdoc = NULL;
    xmlNodePtr proot = NULL;
    
    /*****************打开xml文档********************/
    xmlKeepBlanksDefault(0);//必须加上,防止程序把元素前后的空白文本符号当作一个node
    pdoc = xmlReadFile ("test.xml", "UTF-8", XML_PARSE_RECOVER);//libxml只能解析UTF-8格式数据
    
    if (pdoc == NULL)
    {
    printf ("error:can't open file!
    ");
    exit (1);
    }
    
    /*****************获取xml文档对象的根节对象********************/
    proot = xmlDocGetRootElement (pdoc);
    
    if (proot == NULL)
    {
    printf("error: file is empty!
    ");
    exit (1);
    }
    
    /*****************查找书店中所有书籍的名称********************/
    xmlChar *xpath = BAD_CAST("//book"); //xpath语句
    xmlXPathObjectPtr result = getNodeset(pdoc, xpath); //查询XPath表达式,得到一个查询结果
    if (result == NULL)
    {
    printf("result is NULL
    ");
    exit (1);
    }
    
    if(result)
    {
    xmlNodeSetPtr nodeset = result->nodesetval; //获取查询到的节点指针集合
    xmlNodePtr cur;
    
    //nodeset->nodeNr是集合元素总数
    for (int i=0; i < nodeset->nodeNr; i++)
    {
    cur = nodeset->nodeTab[i];
    cur = cur->xmlChildrenNode;
    
    while (cur != NULL)
    {
    //如同标准C中的char类型一样,xmlChar也有动态内存分配,字符串操作等 相关函数。例如xmlMalloc是动态分配内存的函数;xmlFree是配套的释放内存函数;xmlStrcmp是字符串比较函数等。
    //对于char* ch="book", xmlChar* xch=BAD_CAST(ch)或者xmlChar* xch=(const xmlChar *)(ch)
    //对于xmlChar* xch=BAD_CAST("book"),char* ch=(char *)(xch)
    if (!xmlStrcmp(cur->name, BAD_CAST("title"))) {
    printf("title: %s
    ",((char*)XML_GET_CONTENT(cur->xmlChildrenNode)));
    break;
    }
    
    cur = cur->next;
    }
    }
    
    xmlXPathFreeObject(result);//释放结果指针
    }
    
    /*****************释放资源********************/
    xmlFreeDoc (pdoc);
    xmlCleanupParser ();
    xmlMemoryDump ();
    
    return 0;
    }


        具体流程我已经在代码中详细注释,这里就不单独拿出来解释。

            更加详细的libxml2接口,可以访问http://xmlsoft.org/html/libxml-tree.html


    编译程序并运行

    编译上述程序

    g++ search1.cpp -I/usr/local/include/libxml2 -L/usr/local/lib -lxml2 -o search1
    g++ search2.cpp -I/usr/local/include/libxml2 -L/usr/local/lib -lxml2 -o search2

    运行程序及运行结果

    运行./search1

    显示如下结果:

    title: Harry Potter
    title: Learning XML


    运行./search2


    显示如下结果:

    title: Harry Potter
    title: Learning XML

    来自:http://blog.csdn.net/l_h2010/article/details/38639143

  • 相关阅读:
    IDEA
    SpringCloud
    Docker
    Docker
    JDK排序
    选择排序
    冒泡排序
    计算一个整数数组的平均数
    (if语句)中国的个税计算方法
    读入一个表示年份的整数,判断这一年是否是闰年
  • 原文地址:https://www.cnblogs.com/catgatp/p/6505451.html
Copyright © 2011-2022 走看看