就TinyXml使用答复一位网友

作者:朱金灿

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

 

 

       一位网友说看了我的TinyXml快速入门系列文章。在修改节点属性值函数ModifyNode_Attribute这个函数的用法参照我的例子运行了下,

<Connection ip="192.168.0.1" timeout="123.456000"/> 如果只有这一个节点的时候是修改正确的,但是如果再加上几个相同名字的节点呢?就像下面一样:

<Connection ip="192.168.0.1" timeout="123.456000"/>
<Connection ip="192.168.0.2" timeout="123.456001"/>
<Connection ip="192.168.0.3" timeout="123.456002"/>

    现在他想修改的是<Connection ip="192.168.0.3" timeout="123.456002"/> 这行为<Connection ip="192.168.0.4" timeout="123.456003"/>

请问该如何修改?

 

     鉴于他所提问题有一定代表性,我就再写一篇以作答复。在《TinyXml快速入门(二)》中我提到了无论查询节点、删除节点、修改节点和增加节点,其实都离不开一个函数,就是根据节点名获取相关节点指针,其中一个关键的函数:

/*!
*  \brief 通过根节点和节点名获取节点指针。
*
*  \param pRootEle   xml文件的根节点。
*  \param strNodeName  要查询的节点名
*  \param Node      需要查询的节点指针
*  \return 是否找到。true为找到相应节点指针,false表示没有找到相应节点指针。
*/
bool GetNodePointerByName(TiXmlElement* pRootEle,const 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;
}

    具体到这位网友的问题,其实就是增加了一个判断条件,就是要求所求节点不但要求节点名为Connection,还有属性ip的值为192.168.0.3。那么我们可以对GetNodePointerByName函数稍作修改:


   
/*!
*  \brief 通过根节点和节点名以及节点的一个属性值获取节点指针。
*
*  \param pRootEle   xml文件的根节点。
*  \param strNodeName  要查询的节点名
*  \param strNodeName  要查询的节点的一个属性值
*  \param Node      需要查询的节点指针
*  \return 是否找到。true为找到相应节点指针,false表示没有找到相应节点指针。
*/
bool GetNodePointerByName_Attribute(TiXmlElement* pRootEle,
                                    
const std::string &strNodeName,
                                    
const std::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;
}

然后再增加一个修改属性的函数:


/*!
*  \brief 修改指定节点的属性。
*
*  \param XmlFile xml文件全路径。
*  \param strNodeName 指定的节点名。
*  \param strAttValue 指定的节点的其中一个属性值。
*  \param AttMap 重新设定的属性值,这是一个map,前一个为属性名,后一个为属性值
*  \return 是否成功。true为成功,false表示失败。
*/
bool ModifyNode_Attribute2(const std::string& XmlFile,const std::string& strNodeName,
                          
const std::string& strAttValue,
                          
const std::map<std::string,std::string> &AttMap)
{
    typedef std::pair 
<std::string,std::string> String_Pair;

    
// 定义一个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_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);
                }
            }

        }  
        pDoc
->SaveFile(XmlFile);
        
return true;
    }
    
else
    {
        
return false;
    }

}

如果要将

<Connection ip="192.168.0.1" timeout="123.456000"/>

<Connection ip="192.168.0.2" timeout="123.456001"/>

<Connection ip="192.168.0.3" timeout="123.456002"/>

 

   中的<Connection ip="192.168.0.3" timeout="123.456002"/> 这行修改为<Connection ip="192.168.0.4" timeout="123.456003"/>

     那么测试代码就如下:

   std::string strNodeName = _T("Connection");
   std::
string strAttValue = _T("192.168.0.3");
  typedef std::pair 
<std::string,std::string> String_Pair;
   std::map
<std::string,std::string> AttMap;
   AttMap.insert(String_Pair(_T(
"ip"),_T("192.168.0.4")));
   AttMap.insert(String_Pair(_T(
"timeout"),_T("123.456003")));
   ModifyNode_Attribute2(XmlFile,strNodeName,strAttValue,AttMap);


 

 

 

 

 

 

 

posted @ 2010-04-11 11:36  是金子就会灿烂  阅读(3014)  评论(1编辑  收藏  举报