1. 程式人生 > >linux下使用libxml2庫,解析xml檔案

linux下使用libxml2庫,解析xml檔案

1.實現功能:讀取一個xml檔案中的內容,節點等資訊!

首先定義了一個test.xml檔案,檔案內容如下:

<?xml version="1.0" encoding="utf-8"?>
<story name="test">
        <content name = "lsp">
                <pro id="moonApple"><![CDATA[<say>i still have lots to work on</say>]]></pro>
                <details>
                        <detail name="dancing">like it</detail>
                        <detail name="singing">poor , just listen</detail>
                        <detail name="laugh"/>
                        <detail name="eating"><![CDATA[<food>candy</food>]]></detail>
                </details>
        </content>
</story>

寫了三個檔案:分別為:testxml.cpp     ReadXml.cpp     ReadXml.h

testxml.cpp內容如下:

#include "ReadXml.h"
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <string>
#include <iostream>

using namespace std;

int main(int argc, char **argv)
{

    //string filename = "parser.xml";
    string filename = "usb.xml";

    ReadXml rx;
    const char* name = (char*)rx.getRootNodeName(filename);
    cout << name << endl;

    const char* content = (char*)rx.getAllContent(filename);
    cout << content << endl;




    xmlDocPtr doc = NULL;
    xmlNodePtr cur = NULL;
    xmlChar* szKey;

    const char *docname = filename.c_str();
    xmlKeepBlanksDefault(0);
    doc = xmlParseFile(docname);
    if(doc == NULL){
        fprintf(stderr, "Document not parse successfully. \n");
        return 0;
    }

    /* obtain root node */
    cur = xmlDocGetRootElement(doc);



    if(cur == NULL){
        fprintf(stderr, "empty document\n");
        xmlFreeDoc(doc);
        return 0;
    }

    cur = cur->xmlChildrenNode;
    //cout << "attributes is :" <<xmlGetProp(cur, (const xmlChar*)"name") << endl;
    cout << "attributes is :" <<rx.getNodeAttributes(cur, (const xmlChar*)"name") << endl << endl;

    const char* nodecontent = (char*)rx.getNodeContent(cur);
    cout << nodecontent << endl;

    cur = cur->next;
    const char* nodeattribute = (char*)rx.getNodeAttributes(cur,  (const xmlChar*)"attributes");
    if (NULL == nodeattribute) {
        cout << "nodeattribute is null!" << endl;
    } else {
        cout << "nodeattribute is:" << nodeattribute << endl;
    }

    //cout << xmlGetProp(cur, (const xmlChar*)"name") << endl;
    return 1;
}

解析:

testxml.cpp檔案中,定義了main函式,主要就是呼叫自定義的實現讀取xml功能的ReadXml類,然後測試在該類中定義的一些函式。下面解釋一下該檔案中用到的一些函式的意思。

首先:

xmlDocPtr doc = NULL;  
xmlNodePtr node = NULL;  
doc = xmlParseFile(filename); 

xmlDocPtr 表示指向xmlDoc的指標。xmlDoc是一個包含了已解析的檔案生成的節點樹的結構體。

xmlDocGetRootElement(doc)可以得到整個檔案的根節點,所有的操作都是從根節點開始的。

xmlGetProp可以得到節點屬性,第一個引數為節點,第二個引數為節點名稱。返回xmlChar型別!

節點包含這麼幾個資訊:

node->name:節點的名字,如node1,node2,subnode等

node->xmlChildrenNode:節點的子節點

node->last:節點的最後一個子節點

node->parent:節點的父節點

node->next:節點的兄弟節點,對於node1來說,node2和node3都是其兄弟節點,node1的next指向node2

由於節點的內容是其子節點(對於node1,content1可以說是其子節點),所以我們需要使用xmlNodeGetContent來取出內容。


如果出現讀取資訊不正確的情況,請看這裡::

libxml預設將各個節點間的空格當作一個節點,只要在呼叫xmlParseFile之前呼叫xmlKeepBlanksDefault(0)即可!

ReadXml.cpp內容如下:

#include <iostream>

#include "ReadXml.h"

using namespace std;

    ReadXml::ReadXml()
    {

    }
    ReadXml::~ReadXml()
    {

    }

    const xmlChar* ReadXml::getRootNodeName(std::string filename)
    {
        const char *docname = filename.c_str();
        xmlKeepBlanksDefault(0);
        doc = xmlParseFile(docname);
        if(doc == NULL){
            fprintf(stderr, "Document not parse successfully. \n");
            return 0;
        }

        /* obtain root node */
        cur = xmlDocGetRootElement(doc);
        if(cur == NULL){
            fprintf(stderr, "empty document\n");
            xmlFreeDoc(doc);
            return 0;
        }

        return cur->name;
        //printf("root node :%s\n", cur->name);
        //szKey = xmlNodeGetContent(cur);
        //printf("all content:\n %s \n", szKey);

    }

    xmlChar* ReadXml::getAllContent(std::string filename)
    {
        const char *docname = filename.c_str();
        xmlKeepBlanksDefault(0);
        doc = xmlParseFile(docname);
        if(doc == NULL){
            fprintf(stderr, "Document not parse successfully. \n");
            return 0;
        }

        /* obtain root node */
        cur = xmlDocGetRootElement(doc);
        if(cur == NULL){
            fprintf(stderr, "empty document\n");
            xmlFreeDoc(doc);
            return 0;
        }

        szKey = xmlNodeGetContent(cur);
        return szKey;
    }

    xmlChar* ReadXml::getNodeContent(xmlNodePtr node)
    {
        return xmlNodeGetContent(node);
    }

    xmlChar* ReadXml::getNodeAttributes(xmlNodePtr node, const xmlChar * name)
    {
        return xmlGetProp(node, name);
        //rerutn value should free use xmlFree(szAttr);
    }



ReadXml.h內容如下:

#include <string>
#include <iostream>
#include <stdio.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>

class ReadXml
{
public:
    ReadXml();
    ~ReadXml();

    const xmlChar* getRootNodeName(std::string filename);
    xmlChar* getAllContent(std::string filename);
    xmlChar* getNodeContent(xmlNodePtr cur);
    xmlChar* getNodeAttributes(xmlNodePtr node, const xmlChar * name);

private:
    xmlDocPtr doc;
    xmlNodePtr cur;
    xmlChar* szKey;

};

編譯程式碼為:
g++ -o testxml.out testxml.cpp ReadXml.cpp -I/usr/include/libxml2/ -lxml2
./testxml.out 

執行結果為:

lsp@liushuanpeng:~/gccConfig$ ./testxml.out 
story
<say>i still have lots to work on</say>like itpoor , just listen<food>candy</food>
attributes is :lsp

<say>i still have lots to work on</say>like itpoor , just listen<food>candy</food>
nodeattribute is null!


參考連結: