TinyXml快速入门(二)

11 篇文章 0 订阅

作者:朱金灿

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

 

在《TinyXml快速入门(一)》中我介绍了使用TinyXml库如何创建和打印xml文件,下面我介绍使用tinyxml库对xml文件进行一系列的操作,包括获取xml文件声明,查询指定节点、删除指定节点、修改指定节点和增加节点的用法。在TinyXml快速入门(一)》中我们知道xml文件中的一个节点元素实际包含两种值:属性和文本。其中属性在我看来可以看作是STL中的map,一个属性带一个属性值,map中也是一个键带一个键值。因此查询指定节点、删除指定节点和增加节点必然是需要实现两种方法,删除指定节点只需要实现一种方法。鉴于内容较多,在本文中介绍获取xml文件声明,查询指定节点、删除指定节点的做法,修改指定节点和增加节点的做法在后续的文章介绍。

 

     首先是获取xml文件声明。xml文件声明包括三方面的内容:Version、Standalone和Encoding。其源码如下:

复制代码
/* !
*  \brief 获取xml文件的声明。
*
*  \param XmlFile xml文件全路径。
*  \param strVersion  Version属性值
*  \param strStandalone Standalone属性值
*  \param strEncoding Encoding属性值
*  \return 是否成功。true为成功,false表示失败。
*/
bool  GetXmlDeclare(std:: string  XmlFile,
                   std::
string   & strVersion,
                   std::
string   & strStandalone,
                   std::
string   & strEncoding)
{
    
//  定义一个TiXmlDocument类指针
    TiXmlDocument  * pDoc  =   new  TiXmlDocument();
    
if  (NULL == pDoc)
    {
        
return   false ;
    }

    pDoc
-> LoadFile(XmlFile);

      TiXmlNode
*  pXmlFirst  =  pDoc -> FirstChild();   
      
if  (NULL  !=  pXmlFirst)  
     {  
          TiXmlDeclaration
*  pXmlDec  =  pXmlFirst -> ToDeclaration();  
          
if  (NULL  !=  pXmlDec)  
          {  
              strVersion 
=  pXmlDec -> Version();
              strStandalone 
=  pXmlDec -> Standalone();
              strEncoding 
=  pXmlDec -> Encoding();
          }
      }
      
return   true ;
}
复制代码

我们发现无论查询节点、删除节点、修改节点和增加节点,其实都离不开一个函数,就是根据节点名获取相关节点指针。那么我们就先实现一个根据节点名获取节点指针的函数:

复制代码
/* !
*  \brief 通过根节点和节点名获取节点指针。
*
*  \param pRootEle   xml文件的根节点。
*  \param strNodeName  要查询的节点名
*  \param Node      需要查询的节点指针
*  \return 是否找到。true为找到相应节点指针,false表示没有找到相应节点指针。
*/
bool  GetNodePointerByName(TiXmlElement *  pRootEle,std:: string   & strNodeName,TiXmlElement *   & Node)
{
     
//  假如等于根节点名,就退出
      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 ;
}
复制代码

有了这个函数,我们就很容易实现查询节点的相应文本或属性值。

复制代码
     /* !
*  \brief 通过节点查询。
*
*  \param XmlFile   xml文件全路径。
*  \param strNodeName  要查询的节点名
*  \param strText      要查询的节点文本
*  \return 是否成功。true为成功,false表示失败。
*/
bool  QueryNode_Text(std:: string  XmlFile,std:: string  strNodeName,std:: string   & strText)
{
    
//  定义一个TiXmlDocument类指针
    TiXmlDocument  * pDoc  =   new  TiXmlDocument();
    
if  (NULL == pDoc)
    {
        
return   false ;
    }

    pDoc
-> LoadFile(XmlFile);
    TiXmlElement 
* pRootEle  =  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 ;
   }
    
}


/* !
*  \brief 通过节点查询。
*
*  \param XmlFile   xml文件全路径。
*  \param strNodeName  要查询的节点名
*  \param AttMap      要查询的属性值,这是一个map,前一个为属性名,后一个为属性值
*  \return 是否成功。true为成功,false表示失败。
*/
bool  QueryNode_Attribute(std:: string  XmlFile,std:: string  strNodeName,std::map < std:: string ,std:: string >   & AttMap)
{
    
//  定义一个TiXmlDocument类指针
    typedef std::pair  < std:: string ,std:: string >  String_Pair;

    TiXmlDocument 
* pDoc  =   new  TiXmlDocument();
    
if  (NULL == pDoc)
    {
        
return   false ;
    }

    pDoc
-> LoadFile(XmlFile);
    TiXmlElement 
* pRootEle  =  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 ;
    }
    
return   true ;
}
复制代码

      下面是删除指定节点的函数,其中考虑了删除根节点的情况。

复制代码
/* !
*  \brief 删除指定节点的值。
*
*  \param XmlFile xml文件全路径。
*  \param strNodeName 指定的节点名。
*  \return 是否成功。true为成功,false表示失败。
*/
bool  DelNode(std:: string  XmlFile,std:: string  strNodeName)
{
    
//  定义一个TiXmlDocument类指针
    TiXmlDocument  * pDoc  =   new  TiXmlDocument();
    
if  (NULL == pDoc)
    {
        
return   false ;
    }

    pDoc
-> LoadFile(XmlFile);
    TiXmlElement 
* pRootEle  =  pDoc -> RootElement();
    
if  (NULL == pRootEle)
    {
        
return   false ;
    }

    TiXmlElement 
* pNode  =  NULL;

    GetNodePointerByName(pRootEle,strNodeName,pNode);

    
//  假如是根节点
     if  (pRootEle == pNode)
    {
          
if (pDoc -> RemoveChild(pRootEle))
          {
               pDoc
-> SaveFile(XmlFile);
               
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))
                 pDoc
-> SaveFile(XmlFile);
            
else
                
return   false ;
        }
    }
    
else
    {
          
return   false ;
    }

     
return   false ;
}


复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值