就TinyXml使用答复一位网友
2010-04-11 11:36
627 查看
作者:朱金灿
来源: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);
来源: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);
相关文章推荐
- 就TinyXml使用答复一位网友
- 就TinyXml使用答复一位网友
- C#热度不如Java?网友呛声:还有使用C#不能完成的工作?
- 使用一位数组解决 1 1 2 3 5 8 13 数列问题 斐波纳契数列 Fibonacci
- Invalidate()mfc函数使用,摘录自csdn以为网友回答。
- 论坛短信中一个关于ADOMD使用的答复。
- 看完一网友使用定义法计算定积分(速度与位移)的C代码而有所感
- 【原创】回答网友关于ARM9 S3C2440 wince6.0 内存 128M的使用问题
- 再谈外企是毒品——回复一位网友
- 一位网友的女友的最后的信
- 转 Android之项目推荐使用的第三方库,有助于快速开发,欢迎各位网友补充
- 分别显示用float和double指数记数法所能表示的最大值和最小值 以一个最高有效位为1的二进制数字开始,用有符号右移操作符对其进行右移,直至所有二进制位都被移除为止,每移一位都要使用Integer
- 程序集版本最后一位使用SVN版本号的自动生成方法
- 答一位网友《SBO有哪样的几种开发方式》
- 一位豆瓣网友为几部经典科学书籍作的勘误(只放链接)
- 网友朋友的关于XML的分类和使用!
- [置顶] Android 使用Ant+Emma+Junit收集android代码覆盖率(来自联想的一位同事2012.12.24)
- 一位iOS开发者使用React Native的体验
- 技术专题:请需要我帮忙抓包分析网络的网友,使用下面的抓包教程,然后将数据包发给我
- 一位网友的项目管理经验