Linux 下C/C++解析XML文件(一)

C/C++解析XML文件

在工程项目中我们的项目需要根据不同的环境配置不同的程序参数,而常用的两种文件分别是ini文件和XML文件,接下来我来分析下在Linux下解析XML文件过程。

我们首先使用linux自带的libxml2来解析XML文件。

1. libxml2数据结构

在libxml2中比较重要的数据结构是xmlNodePtr,它在libxml/tree.h中定义为

/** 
 * xmlNode: 
 * 
 * A node in an XML tree. 
 */  
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 */  
    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 */  

    /* End of common part */  
    xmlNs           *ns;        /* pointer to the associated namespace */  
    xmlChar         *content;   /* the 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 */  
};  

2. 解析代码

#include <stdio.h>  
#include <unistd.h>  
#include <sys/types.h>  
#include <string.h>

#include <libxml/parser.h>  
#include <libxml/xmlmemory.h>  
/  
//

#if 0
int main(int argc, char* argv[])
{
    xmlDocPtr doc;           //定义解析文档指针
    xmlNodePtr curNode;      //定义结点指针(你需要它为了在各个结点间移动)
    xmlChar *szKey;          //临时字符串变量
    char *szDocName;

    if (argc <= 1) 
    {
       printf("Usage: %s docname\n", argv[0]);
       return(0);
    }

    szDocName = argv[1];
    doc = xmlReadFile(szDocName,"UTF-8",XML_PARSE_RECOVER); //解析文件

    //检查解析文档是否成功,如果不成功,libxml将指一个注册的错误并停止。
    //一个常见错误是不适当的编码。XML标准文档除了用UTF-8或UTF-16外还可用其它编码保存。
    //如果文档是这样,libxml将自动地为你转换到UTF-8。更多关于XML编码信息包含在XML标准中.

    if (NULL == doc)
    {  
       fprintf(stderr, "xmlParseFile Error in %s %d\n",__FUNCTION__, __LINE__);
       return -1;
    }

    curNode = xmlDocGetRootElement(doc); //确定文档根元素
    if (NULL == curNode)
    {
       fprintf(stderr, "xmlDocGetRootElement Error in %s %d\n", __FUNCTION__, __LINE__);
       xmlFreeDoc(doc);
       return -1;
    }

    printf("Node name is %s!\n", pRoot->name);

    if (xmlStrcmp(curNode->name, BAD_CAST "root"))
    {
       fprintf(stderr,"document of the wrong type, root node != root\n");
       xmlFreeDoc(doc);
       return -1;
    }

    curNode = curNode->xmlChildrenNode; //子节点集是链表
    xmlNodePtr propNodePtr = curNode;
    while(curNode != NULL)
    {
       //取出节点中的内容
       if ((!xmlStrcmp(curNode->name, (const xmlChar *)"monitor")))
       {
           szKey = xmlNodeGetContent(curNode);
           printf("newNode1: %s\n", szKey);
           xmlFree(szKey);
       }

       //查找带有属性attribute的节点
       if (xmlHasProp(curNode,BAD_CAST "attribute"))
       {
           propNodePtr = curNode;
       }
       curNode = curNode->next;
    }

    //查找属性
    xmlAttrPtr attrPtr = propNodePtr->properties; //属性集是链表
    while (attrPtr != NULL)
    {
       if (!xmlStrcmp(attrPtr->name, BAD_CAST "attribute"))
       {
           xmlChar* szAttr = xmlGetProp(propNodePtr,BAD_CAST "attribute");
   //szAttr要调用函数xmlFree(szAttr)手动删除否则会发生内存泄露。
//           cout<<"get attribute = "<<szAttr<<endl;
           xmlFree(szAttr);
       }
       attrPtr = attrPtr->next;
    }

    xmlFreeDoc(doc);
    return 0;

}
#endif

int main(int argc, const char *argv[])
{
    if(2 != argc)
    {
        fprintf(stdout, "Please statrt this program with %s xmlfilepath!", argv[0]);
        return 1;
    }
    xmlDocPtr pDoc = xmlReadFile(argv[1], "UTF-8", XML_PARSE_RECOVER); //获取XML文档的指针
    if(NULL == pDoc)
    {
        fprintf(stderr, "xmlParseFile Error in %s %d\n",__FUNCTION__, __LINE__);
        return -1;
    }

    xmlNodePtr pRoot = xmlDocGetRootElement(pDoc);//获取根节点
    if(NULL == pRoot)
    {
        fprintf(stderr, "xmlDocGetRootElement Error in %s %d\n", __FUNCTION__, __LINE__);
        xmlFreeDoc(pDoc);
        return -1;
    }

    printf("Node name is %s!\n", pRoot->name);

    xmlNodePtr pFirst = pRoot->xmlChildrenNode;//获取子节点
    while(NULL != pFirst)
    {
        if(!xmlStrcmp(pFirst->name, (const xmlChar *)("monitor")))
        {
            xmlNodePtr pSecond = pFirst->xmlChildrenNode;
            while(NULL != pSecond)
            {
                xmlChar* value= NULL;

                if(!xmlStrcmp(pSecond->name, (const xmlChar *)("name")))
                {
                    value = xmlNodeGetContent(pSecond);
                    printf("\n%s-->%s\n", pSecond->name, value);
                    xmlFree(value);
                    value = NULL;
                }

                if(!xmlStrcmp(pSecond->name, (const xmlChar *)("path")))
                {
                    value = xmlNodeGetContent(pSecond);
                    printf("\n%s-->%s\n", pSecond->name, value);
                    xmlFree(value);
                    value = NULL;
                }

                if(!xmlStrcmp(pSecond->name, (const xmlChar *)("log")))
                {
                    xmlNodePtr pThird = pSecond->xmlChildrenNode;
                    while(NULL != pThird)
                    {
                        if(!xmlStrcmp(pThird->name, (const xmlChar *)("folderpath")))
                        {
                            value = xmlNodeGetContent(pThird);
                            printf("\n%s-->%s\n", pThird->name, value);
                            xmlFree(value);
                            value = NULL;
                        }

                        if(!xmlStrcmp(pThird->name, (const xmlChar *)("savedays")))
                        {
                            value = xmlNodeGetContent(pThird);
                            printf("\n%s-->%s\n", pThird->name, value);
                            xmlFree(value);
                            value = NULL;
                        }

                        pThird = pThird->next;
                    }
                }

                pSecond = pSecond->next;
            }
        }

        pFirst = pFirst->next;
    }
    xmlFreeDoc(pDoc);
    return 0;
}

3. 被解析xml文件

<?xml version="1.0" encoding="UTF-8"?>  
<root>  
    <monitor>  
        <name>ftp</name>   <!--监控的程序名称-->  
        <path>/usr/bin/</path>   <!--程序绝对路径-->  
        <interval>30</interval>  <!--间隔多久监控一次-->  
        <restartwait>30</restartwait>  <!--程序被重启后,等待多久再进行监控-->  
        <ip>127.0.0.1</ip>   <!--程序IP-->  
        <port>9878</port>    <!--程序端口-->  
        <request>1;monitor</request>    <!--发送给程序的报文-->  
        <response>The ftp is working ok.</response>   <!--程序给监控的反馈报文-->  
        <log>  
            <folderpath>log/</folderpath>  <!--程序日志保存目录-->  
            <savedays>2</savedays>     <!--程序日志保存时间-->  
        </log>  
    </monitor>  
</root> 

4. 编译

#!/bin/sh
gcc test.c -o test -lxml2 -I/usr/include/libxml2

5. 结果

sean@sean:~/tmp/xml2$ ./test test-1.xml 
Node name is root!

name-->ftp

path-->/usr/bin/

folderpath-->log/

savedays-->2

出处

————————————————
版权声明:本文为CSDN博主「bingyu9875」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/bingyu9875/article/details/80702119

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值