TinyXML簡介
TinyXML是目前非常流行的一款基于DOM模型的XML解析器,簡單易用且小巧玲瓏,非常適合存儲(chǔ)簡單數(shù)據(jù),配置文件,對象序列化等數(shù)據(jù)量不是很大的操作,尤其適用于游戲開發(fā),在Nebula2,CEGUI等開源項(xiàng)目中都有使用。本文對TinyXML讀寫XML文件進(jìn)行了重新封裝,能方便的解決XML文檔讀寫。
關(guān)于DOM和SAX
DOM - Document Object Model
將整篇XML文檔一次性解析并讀入內(nèi)存,保存為一個(gè)對象供用戶訪問。
SAX - Simple API for XML
SAX的XML解析方式是基于事件回調(diào)的,解析器在每遇到一個(gè)XML元素時(shí)都會(huì)產(chǎn)生一個(gè)事件,并執(zhí)行由用戶提供的處理函數(shù)。
TinyXML類結(jié)構(gòu)
[TiXmlBase] 所有TinyXML類的基類,保存該結(jié)點(diǎn)或?qū)傩栽赬ML原文中的信息。
[TiXmlAttribute] XML結(jié)點(diǎn)屬性,一個(gè)鍵值對
[TiXmlNode] XML結(jié)點(diǎn)的基類,封裝了對XML文檔樹形結(jié)構(gòu)進(jìn)行操作和維護(hù)的方法
[TiXmlComment] XML注釋結(jié)點(diǎn)
[TiXmlDeclaration] XML聲明結(jié)點(diǎn)
[TiXmlDocument] XML文檔結(jié)點(diǎn)(一般為一篇XML文檔的根結(jié)點(diǎn))
[TiXmlElement] XML結(jié)點(diǎn)
[TiXmlText] XML文本結(jié)點(diǎn)
[TiXmlUnknown] 含有未知標(biāo)簽的XML結(jié)點(diǎn)
[TiXmlHandle] 封裝了一個(gè)結(jié)點(diǎn)的指針,在對該指針進(jìn)行查詢時(shí)將自動(dòng)進(jìn)行空指針交驗(yàn)
[TiXmlVisitor] 遍歷器接口,描述了每個(gè)節(jié)點(diǎn)的處理方法,由子類實(shí)現(xiàn)
[TiXmlPrinter] Printer遍歷器
l 讀取XML文件
TiXmlDocument doc("test.xml");
doc.LoadFile("test.xml");
l 寫入XML文件
TiXmlDocument doc;
……
doc.SaveFile("test.xml");
l 遍歷XML文檔
首先以FirstChild獲得第一個(gè)自節(jié)點(diǎn),然后以NextSibling獲取下個(gè)兄弟節(jié)點(diǎn);如此遞歸遍歷所有節(jié)點(diǎn)即可。
TiXmlNode::FirstChild();
TiXmlNode::NextSibling();
l 構(gòu)造XML文檔
將指定節(jié)點(diǎn)插入當(dāng)前節(jié)點(diǎn)子節(jié)點(diǎn)隊(duì)列的末尾
TiXmlNode::LinkEndChild();
設(shè)置指定節(jié)點(diǎn)的屬性
TiXmlElement::SetAttribute();
TiXmlElement::SetDoubleAttribute();
XML讀寫的邏輯封裝
針對不同的應(yīng)用對XML的讀寫進(jìn)行再次封裝能提升工作的效率和代碼的可讀性等。
#pragma once
#include "stdafx.h"
#include "tinyxml.h"

//XML 文件的讀寫

class AttXMLDoc

...{
public:
AttXMLDoc(void);
~AttXMLDoc(void);

//XML讀寫迭代器
void BeginExchange(const char* szFileName,const char* szAttName,bool bSave);
bool NextAtt();

//讀寫XML節(jié)點(diǎn)
void ExchangeField(const char* szFieldName,DWORD& val);
void ExchangeField(const char* szFieldName,WORD& val);
void ExchangeField(const char* szFieldName,BYTE& val);
void ExchangeField(const char* szFieldName,int& val);
void ExchangeField(const char* szFieldName,bool& val);
void ExchangeField(const char* szFieldName,float& val);
void ExchangeField(const char* szFieldName,char* szValBuf,int bufLen);

//XML讀寫迭代器
void EndExchange();

private:
TiXmlDocument m_doc;
TiXmlElement *m_rootElement;
TiXmlElement *m_curElement;
bool m_bSave;
string m_szName;
};
源文件實(shí)現(xiàn):
#include "StdAfx.h"
#include ".attxmldoc.h"

AttXMLDoc::AttXMLDoc(void)

...{
m_curElement = NULL;
m_rootElement = NULL;
m_bSave = true;
}

AttXMLDoc::~AttXMLDoc(void)

...{
}

char eleName[256]="Att";
void AttXMLDoc::BeginExchange(const char* szFileName,const char* szAttName,bool bSave)

...{
m_bSave = bSave;
m_szName = szFileName;

if(bSave)

...{
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0","GB2312","yes");
m_doc.LinkEndChild(decl);
m_rootElement = new TiXmlElement(szAttName);
m_doc.LinkEndChild(m_rootElement);
}
else

...{
m_doc.LoadFile(szFileName);
m_rootElement = m_doc.RootElement();
m_curElement = m_rootElement->FirstChildElement(eleName);
}
}

bool AttXMLDoc::NextAtt()

...{
if(m_bSave)

...{
if(m_curElement != NULL)
m_rootElement->LinkEndChild(m_curElement);
m_curElement = new TiXmlElement(eleName);
return true;
}
else

...{
m_curElement = m_curElement->NextSiblingElement(eleName);
return m_curElement!=NULL;
}
}

void AttXMLDoc::ExchangeField(const char* szFieldName,int& val)

...{
ASSERT(m_curElement != NULL );
if(m_bSave)

...{
m_curElement->SetAttribute(szFieldName,val);
}
else

...{
const char* szFind = m_curElement->Attribute(szFieldName,&val);
ASSERT(szFind != NULL);
}
}

void AttXMLDoc::ExchangeField(const char* szFieldName,bool& val)

...{
ASSERT(m_curElement != NULL );

if(m_bSave)

...{
m_curElement->SetAttribute(szFieldName,val);
}
else

...{
int _val = 0;
const char* szFind = m_curElement->Attribute(szFieldName,&_val);
ASSERT(szFind != NULL);
val = _val!=0 ;
}
}

void AttXMLDoc::ExchangeField(const char* szFieldName,WORD& val)

...{
ASSERT(m_curElement != NULL );

if(m_bSave)

...{
m_curElement->SetAttribute(szFieldName,val);
}
else

...{
int _val = 0;
const char* szFind = m_curElement->Attribute(szFieldName,&_val);
ASSERT(szFind != NULL);
val = (WORD)_val ;
}
}

void AttXMLDoc::ExchangeField(const char* szFieldName,BYTE& val)

...{
ASSERT(m_curElement != NULL );

if(m_bSave)

...{
m_curElement->SetAttribute(szFieldName,val);
}
else

...{
int _val = 0;
const char* szFind = m_curElement->Attribute(szFieldName,&_val);
ASSERT(szFind != NULL);
val = (BYTE)_val ;
}
}

void AttXMLDoc::ExchangeField(const char* szFieldName,DWORD& val)

...{
ASSERT(m_curElement != NULL );

if(m_bSave)

...{
m_curElement->SetAttribute(szFieldName,val);
}
else

...{
int _val = 0;
const char* szFind = m_curElement->Attribute(szFieldName,&_val);
ASSERT(szFind != NULL);
val = _val;
}
}

void AttXMLDoc::ExchangeField(const char* szFieldName,float& val)

...{
ASSERT(m_curElement != NULL );

if(m_bSave)

...{
m_curElement->SetDoubleAttribute(szFieldName,val);
}
else

...{
double _val = 0;
const char* szFind = m_curElement->Attribute(szFieldName,&_val);
ASSERT(szFind != NULL);
val = (float)_val;
}
}


void AttXMLDoc::ExchangeField(const char* szFieldName,char* szValBuf,int bufLen)

...{
ASSERT(m_curElement != NULL );

if(m_bSave)

...{
m_curElement->SetAttribute(szFieldName,szValBuf);
}
else

...{
const char* szFind = m_curElement->Attribute(szFieldName);
if(szFind != NULL)
strncpy(szValBuf,szFind,bufLen-1);
}
}

void AttXMLDoc::EndExchange()

...{
if(m_bSave)

...{
if(m_curElement != NULL)

...{
m_rootElement->LinkEndChild(m_curElement);
m_doc.SaveFile(m_szName.c_str());
}
}
}
讀寫XML文件實(shí)例:(略)
XML文件的讀寫在開發(fā)中起這很重要的作用,C++本身沒有提供XML解析器,TinyXML是一個(gè)小巧高效實(shí)用的XML文檔解析器,好好利用起來會(huì)很大程度上提升工作效率。