大型的數據可以存儲到數據庫中,某些數據量很小或者配置文件可以存儲到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;
}