作者:朱金灿
来源:http://blog.csdn.net/clever101/
在TinyXml快速入门的系列文章中(详情见本博客),我只是将tinyxml类库解析xml文件的类封装为API接口。这次我决定将这些API接口对象化,并结合自定义的数据结构解析xml文件。
具体是新建一个CXmlParse类,头文件声明如下:
#include #include #include
实现文件的代码如下:
#include #include "XmlParse.h" CXmlParse::CXmlParse(void) { m_pDoc = NULL; m_strXmlFile = _T(""); } CXmlParse::~CXmlParse(void) { delete m_pDoc; } bool CXmlParse::OpenXml(const string& XmlFile) { if (NULL!=m_pDoc) { delete m_pDoc; m_pDoc = NULL; } m_pDoc = new TiXmlDocument(); if (NULL==m_pDoc) { return false; } m_pDoc->LoadFile(XmlFile); m_strXmlFile = XmlFile; return true; } void CXmlParse::PaintXml() { assert(NULL!=m_pDoc); m_pDoc->Print(); } bool CXmlParse::GetXmlDeclare(string &strVersion,string &strStandalone,string &strEncoding) { assert(NULL!=m_pDoc); // 找到第一个节点 TiXmlNode* pXmlFirst = m_pDoc->FirstChild(); if (NULL != pXmlFirst) { TiXmlDeclaration* pXmlDec = pXmlFirst->ToDeclaration(); if (NULL != pXmlDec) { // 获取各种信息 strVersion = pXmlDec->Version(); strStandalone = pXmlDec->Standalone(); strEncoding = pXmlDec->Encoding(); } } return true; } bool CXmlParse::GetNodePointerByName(TiXmlElement* pRootEle,const string &strNodeName,TiXmlElement* &Node) { assert(NULL!=pRootEle); if (strNodeName==pRootEle->Value()) { Node = pRootEle; return true; } TiXmlElement* pEle = pRootEle; for (pEle = pRootEle->FirstChildElement();pEle;pEle = pEle->NextSiblingElement()) { //递归处理子节点 if(GetNodePointerByName(pEle,strNodeName,Node)) return true; } return false; } bool CXmlParse::GetNodePointerByName_Attribute(TiXmlElement* pRootEle, const string &strNodeName, const string &strAttributeValue, TiXmlElement* &Node) { assert(NULL!=pRootEle); // 假如等于根节点名,就退出 if (strNodeName==pRootEle->Value()) { TiXmlAttribute* pAttr = NULL; for (pAttr = pRootEle->FirstAttribute(); pAttr; pAttr = pAttr->Next()) { std::string strAttValue = pAttr->Value(); if (strAttributeValue==strAttValue) { Node = pRootEle; } } } TiXmlElement* pEle = pRootEle; for (pEle = pRootEle->FirstChildElement(); pEle; pEle = pEle->NextSiblingElement()) { //递归处理子节点 if(GetNodePointerByName_Attribute(pEle,strNodeName,strAttributeValue,Node)) return true; } return false; } bool CXmlParse::QueryNode_Text(const string& strNodeName,string &strText) { assert(NULL!=m_pDoc); TiXmlElement *pRootEle = m_pDoc->RootElement(); if (NULL==pRootEle) { return false; } TiXmlElement *pNode = NULL; GetNodePointerByName(pRootEle,strNodeName,pNode); if (NULL!=pNode) { const char* psz = pNode->GetText(); if (NULL==psz) { strText = _T(""); } else { strText = psz; } return true; } else { return false; } } bool CXmlParse::QueryNode_Attribute(const string& strNodeName,map &AttMap) { assert(NULL!=m_pDoc); typedef std::pair String_Pair; TiXmlElement *pRootEle = m_pDoc->RootElement(); if (NULL==pRootEle) { return false; } TiXmlElement *pNode = NULL; GetNodePointerByName(pRootEle,strNodeName,pNode); if (NULL!=pNode) { TiXmlAttribute* pAttr = NULL; for (pAttr = pNode->FirstAttribute(); pAttr; pAttr = pAttr->Next()) { std::string strAttName = pAttr->Name(); std::string strAttValue = pAttr->Value(); AttMap.insert(String_Pair(strAttName,strAttValue)); } return true; } else { return false; } } bool CXmlParse::DelNode(const string& strNodeName) { assert(NULL!=m_pDoc); TiXmlElement *pRootEle = m_pDoc->RootElement(); if (NULL==pRootEle) { return false; } TiXmlElement *pNode = NULL; GetNodePointerByName(pRootEle,strNodeName,pNode); // 假如要删除的是根节点 if (pRootEle==pNode) { if(m_pDoc->RemoveChild(pRootEle)) { m_pDoc->SaveFile(m_strXmlFile); return true; } else return false; } // 假如要删除的是其它节点 if (NULL!=pNode) { TiXmlNode *pParNode = pNode->Parent(); if (NULL==pParNode) { return false; } TiXmlElement* pParentEle = pParNode->ToElement(); if (NULL!=pParentEle) { if(pParentEle->RemoveChild(pNode)) m_pDoc->SaveFile(m_strXmlFile); else return false; } } else { return false; } return false; } bool CXmlParse::ModifyNode_Text(const string& strNodeName,const string& strText) { assert(NULL!=m_pDoc); TiXmlElement *pRootEle = m_pDoc->RootElement(); if (NULL==pRootEle) { return false; } TiXmlElement *pNode = NULL; GetNodePointerByName(pRootEle,strNodeName,pNode); if (NULL!=pNode) { pNode->Clear(); // 首先清除所有文本 // 然后插入文本,保存文件 TiXmlText *pValue = new TiXmlText(strText); pNode->LinkEndChild(pValue); m_pDoc->SaveFile(m_strXmlFile); return true; } else return false; } bool CXmlParse::ModifyNode_Attribute(const string& strNodeName, const map& AttMap) { assert(NULL!=m_pDoc); typedef std::pair String_Pair; TiXmlElement *pRootEle = m_pDoc->RootElement(); if (NULL==pRootEle) { return false; } TiXmlElement *pNode = NULL; GetNodePointerByName(pRootEle,strNodeName,pNode); if (NULL!=pNode) { TiXmlAttribute* pAttr = NULL; std::string strAttName = _T(""); std::string strAttValue = _T(""); for (pAttr = pNode->FirstAttribute(); pAttr; pAttr = pAttr->Next()) { strAttName = pAttr->Name(); std::map::const_iterator iter; for (iter=AttMap.begin();iter!=AttMap.end();iter++) { if (strAttName==iter->first) { pAttr->SetValue(iter->second); } } } m_pDoc->SaveFile(m_strXmlFile); return true; } else { return false; } } bool CXmlParse::ModifyNode_Attribute2(string strNodeName,string strAttValue, const map &AttMap) { assert(NULL!=m_pDoc); typedef std::pair String_Pair; TiXmlElement *pRootEle = m_pDoc->RootElement(); if (NULL==pRootEle) { return false; } TiXmlElement *pNode = NULL; GetNodePointerByName_Attribute(pRootEle,strNodeName,strAttValue,pNode); if (NULL!=pNode) { TiXmlAttribute* pAttr = NULL; std::string strAttName = _T(""); std::string strAttValue = _T(""); for (pAttr = pNode->FirstAttribute(); pAttr; pAttr = pAttr->Next()) { strAttName = pAttr->Name(); std::map::const_iterator iter; for (iter=AttMap.begin();iter!=AttMap.end();iter++) { if (strAttName==iter->first) { pAttr->SetValue(iter->second); } } } m_pDoc->SaveFile(m_strXmlFile); return true; } else { return false; } } bool CXmlParse::GetAppInfo(MyAppInfo& Info) { map AttMap; bool bSucc = QueryNode_Attribute(string(_T("Framework")),AttMap); std::map::iterator iter; for (iter=AttMap.begin();iter!=AttMap.end();iter++) { if (string(_T("AppName"))==iter->first) { Info.m_strAppName = iter->second; } else if (string(_T("company"))==iter->first) { Info.m_strCompanyName = iter->second; } else if (string(_T("url"))==iter->first) { Info.m_strUrl = iter->second; } } return bSucc; }
注意,上面的CXmlParse类在封装API接口操作的同时,结合一个用户自定义结构MyAppInfo来解析xml文件的内容。
简单测试:
Xml文件的内容如下:
现在我们要获取Framework节点的信息,将其填充到MyAppInfo类型的变量中,具体代码如下:
CXmlParse SysSetting; SysSetting.OpenXml(string(_T("F://MyTest//MyTest//src//outdir//debug//SysConfig.xml"))); MyAppInfo Info; SysSetting.GetAppInfo(Info);