Linux下用Libxml2讀寫XML文檔

大型的數據可以存儲到數據庫中,某些數據量很小或者配置文件可以存儲到XML這種半結構化的文檔中,XML將數據組織成爲一棵樹,DOM通過解析XML文檔,爲XML文檔在邏輯上建立一個樹模型,樹的節點是一個個的對象。這樣通過操作這棵樹和這些對象就可以完成對XML文檔的操作,爲處理文檔的所有方面提供了一個完美的概念性框架。xml 文檔的操作其根本原理就是在節點之間移動、查詢節點的各項信息,並進行增加、刪除、修改的操作。 xmlDocSetRootElement 函數可以將一個節點設置爲某個文檔的根節點,這是將文檔與節點連接起來的重要手段,當有了根結點以後,所有子節點就可以依次連接上根節點,從而組織成爲一個 xml 樹。

libxml 是針對 C 語言的一套 操作XML文檔的API 接口。創建XML文檔的步驟爲:

1)用 xmlNewDoc 函數創建一個文檔指針 doc;
2)用 xmlNewNode 函數創建一個節點指針 root_node;
3)用 xmlDocSetRootElement 將 root_node 設置爲 doc 的根節點;
4)給 root_node 添加一系列子節點,並設置字節點的內容和屬性;
5)用 xmlSaveFile 保存 xml 到文件;
6)用 xmlFreeDoc 函數關閉文檔指針,清除內存。

解析一個xml文檔,從中取出想要的信息,例如節點中包含的文字,或者某個節點的屬性,其流程如下:

1)用 xmlReadFile 函數讀出一個文檔指針 doc ;
2)用 xmlDocGetRootElement 函數得到根節點 curNode ;
3)curNode->xmlChildrenNode 就是根節點的子節點集合 ;
4)輪詢子節點集合,找到所需的節點,用 xmlNodeGetContent 取出其內容 ;
5)用 xmlHasProp 查找含有某個屬性的節點 ;
6)取出該節點的屬性集合,用 xmlGetProp 取出其屬性值 ;
7)用 xmlFreeDoc 函數關閉文檔指針,並清除本文檔中所有節點動態申請的內存。

XmlStore.h

#ifndef XMLSTORE_H
#define XMLSTORE_H
#include <libxml/parser.h>
#include <libxml/tree.h>  
#include "Base64.h"
class Xml{
public:
   Xml();
   ~Xml();
   bool haveXml()const;
   bool createXml(int);
   int parseXml();
   bool saveXml();
   bool setHighScore(int);
private:
   xmlDocPtr pdoc;
   xmlNodePtr proot;  
   xmlNodePtr curNode;
   Base64 *base64;
};
#endif

XmlStroe.cpp

#include "XmlStore.h"
#include <stdlib.h>
#include <unistd.h>  //for access
#include <iostream>
using namespace std;
Xml::Xml():pdoc(NULL),proot(NULL),curNode(NULL){
   base64 = Base64::getInstance();
}
Xml::~Xml(){
   if(pdoc){
      xmlFreeDoc(pdoc);
      pdoc = NULL;
      xmlCleanupParser();
      xmlMemoryDump();
   }
}
bool Xml::haveXml()const{
   if(access("./res/score.xml",F_OK) < 0)
      return false;
   else
      return true;
}
bool Xml::createXml(int value){
   pdoc = xmlNewDoc(BAD_CAST "1.0");
   proot = xmlNewNode(NULL, BAD_CAST "XML");
   xmlNewProp(proot, BAD_CAST "版本", BAD_CAST "1.0");
   xmlDocSetRootElement(pdoc, proot);
   char temp[4];
   sprintf(temp,"%d",value);
   string entropy( base64->base64_encode(temp,4) );
   xmlNewTextChild(proot, NULL, BAD_CAST "configure", BAD_CAST(entropy.c_str() ));
   return true;
}
int Xml::parseXml(){
   pdoc = xmlReadFile ("./res/score.xml","UTF-8", XML_PARSE_RECOVER);
   if(pdoc == NULL)
   {
      cout<<"打開文件 "<<"./res/score.xml."<<" 出錯!\n";
      exit (1);
   }
   proot = xmlDocGetRootElement(pdoc);
   if(proot == NULL)
   {
      cout<<"./res/score.xm."<<" 是空文檔!\n";
      exit (1);
   }
   if(xmlStrcmp(proot->name, BAD_CAST "XML") != 0)
   {
    cout<<"錯誤文檔\n";
    exit (1);
   }
   curNode = proot->xmlChildrenNode;
   curNode = curNode->next; //for the first node
   xmlChar *str = xmlNodeGetContent(curNode);
   string unentropy( ((const char*)BAD_CAST(str)) );
   string integer = base64->base64_decode(unentropy);
   return atoi(integer.c_str());
}
bool Xml::setHighScore(int value){
   curNode = proot->xmlChildrenNode;
   curNode = curNode->next; //for the first node
   if(!curNode)
      cout<<"kong";
   if(!xmlStrcmp(curNode->name, BAD_CAST "configure"))
   {
      char temp[4];
      sprintf(temp,"%d",value);
      string entropy = base64->base64_encode(temp,4);
      xmlNodeSetContent(curNode, BAD_CAST(entropy.c_str()));
   }
   return true;
}
bool Xml::saveXml(){
   xmlSaveFormatFileEnc("./res/score.xml", pdoc, "UTF-8", 1);
   return true;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章