将TinyXml快速入门的接口面向对象化

作者:朱金灿

来源:http://www.cnblogs.com/clever101

 

 

在TinyXml快速入门的系列文章中(详情见本博客),我只是将tinyxml类库解析xml文件的类封装为API接口。这次我决定将这些API接口对象化,并结合自定义的数据结构解析xml文件。

 

     具体是新建一个CXmlParse类,头文件声明如下:

#include <string>
#include 
<vector>
#include 
<map>
#include 
"..\tinyxml\tinyxml.h"
#include 
"BaseStruct.h"
using std::string;
using std::vector;
using std::map;


/*! \struct MyAppInfo XmlParse.h 
* \brief 程序信息结构体.
*
*   包含了程序名、公司名和公司网址
*/
struct MyAppInfo 
{
     MyAppInfo()
     {
         m_strAppName 
= _T("");
         m_strCompanyName  
= _T("") ;
         m_strUrl  
= _T("") ;
     }

    
string m_strAppName;
    
string m_strCompanyName;
    
string m_strUrl;
};
/*! \class CXmlParse XmlParse.h 
*  \brief xml文件解析类
*
*    实现对xml文件的查询、修改和删除节点操作
*  \author 朱金灿.
*  \version 0.1
*  \date    2010.03.28.
*/
class CXmlParse
{
public:
    CXmlParse(
void);
    
~CXmlParse(void);

public:

    
/*!
    *  \brief 打开xml文件。
    *
    *  \param [in]XmlFile xml文件全路径。
    *  \return 是否成功。true为成功,false表示失败。
    
*/
    
bool OpenXml(const string& XmlFile);

    
/*!
    *  \brief 在控制台上打印xml文件。
    *
    *  \return 无。
    
*/
    
void PaintXml();

    
/*!
    *  \brief 获取xml文件的声明。
    *
    *  \param strVersion  [in][out]Version属性值
    *  \param strStandalone [in][out]Standalone属性值
    *  \param strEncoding [in][out]Encoding属性值
    *  \return 是否成功。true为成功,false表示失败。
    
*/
    
bool GetXmlDeclare(string &strVersion,string &strStandalone,string &strEncoding);

    
/*!
    *  \brief 通过节点查询。
    *
    *  \param strNodeName  [in]要查询的节点名
    *  \param strText      [in][out]查询的结果节点文本
    *  \return 是否找到。true为成功找到,false表示没有找到。
    
*/
    
bool QueryNode_Text(const string& strNodeName,string &strText);

    
/*!
    *  \brief 通过节点查询。
    *
    *  \param strNodeName  [in]要查询的节点名
    *  \param AttMap      [in][out]查询的结果属性值,这是一个map,前一个为属性名,后一个为属性值
    *  \return 是否成功。true为成功,false表示失败。
    
*/
    
bool QueryNode_Attribute(const string& strNodeName,map<string,string> &AttMap);

    
/*!
    *  \brief 删除指定节点的值。
    *
    *  \param strNodeName [in]指定的节点名。
    *  \return 是否成功。true为成功,false表示失败。
    
*/
    
bool DelNode(const string& strNodeName);

    
/*!
    *  \brief 修改指定节点的文本。
    *
    *  \param strNodeName [in]指定的节点名。
    *  \param strText [in]重新设定的文本的值
    *  \return 是否成功。true为成功,false表示失败。
    
*/
    
bool ModifyNode_Text(const string& strNodeName,const string& strText);

    
/*!
    *  \brief 修改指定节点的属性。
    *
    *  \param [in]strNodeName 指定的节点名。
    *  \param [in]AttMap 重新设定的属性值,这是一个map,前一个为属性名,后一个为属性值
    *  \return 是否成功。true为成功,false表示失败。
    
*/
    
bool ModifyNode_Attribute(const string& strNodeName,
          
const map<string,string>& AttMap);

    
/*!
    *  \brief 修改指定节点的属性。
    *
    *  \param [in]strNodeName 指定的节点名。
    *  \param [in]strAttValue 指定的节点的其中一个属性值。
    *  \param [in]AttMap 重新设定的属性值,这是一个map,前一个为属性名,后一个为属性值
    *  \return 是否成功。true为成功,false表示失败。
    
*/
    
bool ModifyNode_Attribute2(string strNodeName,string strAttValue,
        
const map<string,string> &AttMap);

public:

    
/*!
    *  \brief 获取应用程序信息。
    *
    *  \param [in][out]Info 指定的节点名。
    *  \return 是否成功。true为成功,false表示失败。
    
*/
   
bool GetAppInfo(MyAppInfo& Info);

private:

    
/*!
    *  \brief 通过根节点和节点名获取节点指针。
    *
    *  \param pRootEle   [in]xml文件的待检查的节点。
    *  \param strNodeName  [in]要查询的节点名。
    *  \param Node      [in][out]需要查询的节点指针。
    *  \return 是否找到。true为找到相应节点指针,false表示没有找到相应节点指针。
    
*/
   
bool GetNodePointerByName(TiXmlElement* pRootEle,const string &strNodeName,TiXmlElement* &Node);

   
/*!
   *  \brief 通过根节点和节点名以及节点的一个属性值获取节点指针。
   *
   *  \param pRootEle   [in]xml文件的待检查的节点。
   *  \param strNodeName  [in]要查询的节点名
   *  \param strNodeName  [in]要查询的节点的一个属性值
   *  \param Node      [in][out]需要查询的节点指针
   *  \return 是否找到。true为找到相应节点指针,false表示没有找到相应节点指针。
   
*/
   
bool GetNodePointerByName_Attribute(TiXmlElement* pRootEle,
       
const string &strNodeName,
       
const string &strAttributeValue,
       TiXmlElement
* &Node);

protected:

    
/**
    * \brief 实际操作xml文件的类。
    
*/
     TiXmlDocument 
*m_pDoc;

     
/**
     * \brief xml文件全路径。
     
*/
     
string m_strXmlFile;
};

实现文件的代码如下:

#include <assert.h>
#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<string,string> &AttMap)
 {
    assert(NULL
!=m_pDoc);
    typedef std::pair 
<std::string,std::string> 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<string,string>& AttMap)
 {
     assert(NULL
!=m_pDoc);
     typedef std::pair 
<std::string,std::string> 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
<std::string,std::string>::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<string,string> &AttMap)
 {
     assert(NULL
!=m_pDoc);
     typedef std::pair 
<std::string,std::string> 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
<std::string,std::string>::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
<string,string> AttMap;
     
bool bSucc = QueryNode_Attribute(string(_T("Framework")),AttMap);
     
     std::map
<std::string,std::string>::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文件的内容如下:

<?xml version="1.0" encoding="GB2312" standalone="no" ?>
<BoostBind>
    
<Framework AppName="boost库测试程序 V1.0" company="BigHardware company" url="http:www.BigHardware.com" />
    
<UIDescription>
        
<AppMenuBar valid="1" caption="文件(F)">
            
<MenuItem valid="1" identity="file_new"  caption="新建" />
            
<MenuItem valid="1" identity="file_open"  caption="打开" />
        
</AppMenuBar>
           
<AppMenuBar valid="1" caption="编辑(E)">
            
<MenuItem valid="1" identity="edit_copy"  caption="拷贝" />
            
<MenuItem valid="1" identity="edit_paste"  caption="粘贴" />
        
</AppMenuBar>
    
</UIDescription>
</BoostBind>

        现在我们要获取Framework节点的信息,将其填充到MyAppInfo类型的变量中,具体代码如下:

 CXmlParse SysSetting;
   SysSetting.OpenXml(
string(_T("F:\\MyTest\\MyTest\\src\\outdir\\debug\\SysConfig.xml")));
MyAppInfo Info;
SysSetting.GetAppInfo(Info);


 

 

 

 

posted @ 2010-04-12 21:17  是金子就会灿烂  阅读(2311)  评论(0编辑  收藏  举报