下载地址 https://github.com/leethomason/tinyxml2
使用 git 下载
(1)下载 tinyxml2
git clone https://github.com/leethomason/tinyxml2.git
(2)进入相应目录并编译
cd tinyxml2/ cmake . make
(3)测试该版本的准确性
./xmltest
(4)安装
sudo make install
可以看到安装的路径
没有 fail 则说明正常。
注意:也可以直接在工程引入 tinyxml2.h 和 tinyxml2.cpp 即可。
TinyXML2 是简单实用的开源的 C++XML 文件解析库,可以很方便的应用到现有的项 目之中。 TinyXML2 解析器相对 TinyXML1 在代码上是完全重写,使其更适合于游戏开发 中使用。它使用更少的内存,更快,并使用更少的内存分配。
由于 XML 的树状结构,TinyXML2 将 XML 的节点抽象为 XMLNode,XML 中除了把属 性 key-value 抽象为 XMLAttribute 类型外,其余的都看作 XMLNode 的子类,首先将整个 XML 文档抽象为 XMLDocument,将声明部分抽象为 XMLDeclaration,将注释抽象为 XMLComment,将元素抽象为 XMLElement,将文本抽象为 XMLText。
2.3 节点 元素 属性 值的关系
XMLAttribute 是解析 XML 的属性的类,XML 中的属性都与 XML 的 Element 绑定,并且为 key-value 类型。
XMLComment 主要是处理 XML 注释的类,注释的存储形式为""。
XMLDeclaration 主要是处理 XML 中声明的类,声明的存储形式为" declaration ?>"。 XMLDocument 代表 XML 整个实体,TinyXML2 中只有 XMLDocument 类可以被实例化,其他的类必
须通过 XMLDocument 提供的 new 方法进行实例化,而不能直接实例化。XMLNode
的其他实体类把构造函数定义为 protected,不能被外部实例化,这样保证使用 XMLDocument 进行内存的管理,避免产生内存泄漏的风险。
XMLElement XMLElement 类是 XMLNode 中最重要的一个类,其存储方式有
XMLHandle 主要用来访问元素。
XMLNode 是几乎 XML 所有元素(XMLAttribute 除外)的基类,XML 本质是一种树形结构,而 整个 XML 就是由许多的节点(XMLNode)组成,在 TinyXML2 中每个 XMLNode 节点都 保存了父亲、前驱、后继、孩子头节点和孩子尾节点信息,便于查询、插入、检 索。
XMLPrinter 是 XMLVisitor 类的子类,主要实现的写 XML 的功能,其提供了两种书写方式,一 是构建 XMLDocument,二是直接 push 字段。
XMLText 主要是处理 XML 文本的类,文本信息又分为 CDATA 和普通文本。CDATA 是有专属的 开始字符"text<"。
XMLUnknown 存储形式为""。
XMLVisitor 访问者模式的基类,它主要定义了访问者的接口,而在 XMLNode 的子类的 accept 方法中调用这些方法来完成对自身的访问。
#include
#include "tinyxml2.h"
int main(void)
{
tinyxml2::XMLDocument doc;
// 本地文件读取
tinyxml2::XMLError ret = doc.LoadFile("local_xml.xml");
std::cout << doc.ErrorID() << std::endl;
std::cout << ret << std::endl;
// 加载到内存
tinyxml2::XMLPrinter printer;
doc.Print(&printer); // 打印到内存
std::cout << printer.CStr() << std::endl;
std::cout << "size: " << printer.CStrSize() << std::endl;
std::cout << "size: " << strlen(printer.CStr()) + 1 << std::endl;
return 0;
}
#include
#include "tinyxml2.h"
int main(void)
{
const char *xml = " \
\
beijing \
shenzhen \
Reminder \
Don't forget the meeting! \
";
tinyxml2::XMLDocument doc;
doc.Parse(xml);
std::cout << doc.ErrorID() << std::endl;
// 1. 第一种刷新到本地
FILE *fp = fopen("memory_1.xml", "wb");
tinyxml2::XMLPrinter printer(fp);
doc.Print(&printer); // 打印到文件,则.CStr()就返回空值了
std::cout << "xml:" << printer.CStr() << std::endl;
fclose(fp);
// 2. 第二种刷新到本地
doc.SaveFile("memory_2.xml");
return 0;
}
#include
#include "tinyxml2.h"
#include
#include
using namespace tinyxml2;
/*
enum XMLError {
XML_SUCCESS = 0,
XML_NO_ATTRIBUTE,
XML_WRONG_ATTRIBUTE_TYPE,
XML_ERROR_FILE_NOT_FOUND,
XML_ERROR_FILE_COULD_NOT_BE_OPENED,
XML_ERROR_FILE_READ_ERROR,
XML_ERROR_PARSING_ELEMENT,
XML_ERROR_PARSING_ATTRIBUTE,
XML_ERROR_PARSING_TEXT,
XML_ERROR_PARSING_CDATA,
XML_ERROR_PARSING_COMMENT,
XML_ERROR_PARSING_DECLARATION,
XML_ERROR_PARSING_UNKNOWN,
XML_ERROR_EMPTY_DOCUMENT,
XML_ERROR_MISMATCHED_ELEMENT,
XML_ERROR_PARSING,
XML_CAN_NOT_CONVERT_TEXT,
XML_NO_TEXT_NODE,
XML_ELEMENT_DEPTH_EXCEEDED,
XML_ERROR_COUNT
};
*/
//创建XML文件
int createXML(const char* xmlPath)
{
XMLDocument doc;
if (XML_ERROR_FILE_NOT_FOUND != doc.LoadFile(xmlPath)) {
std::cout << "file has been existed !" << std::endl;
return 0;
}
//添加声明
XMLDeclaration *declaration = doc.NewDeclaration();
doc.InsertFirstChild(declaration);
XMLElement *root = doc.NewElement("Users");
doc.InsertEndChild(root);
XMLElement *userNode = doc.NewElement("User");
//添加属性
userNode->SetAttribute("Name", "milo");
userNode->SetAttribute("Password", "pwd");
root->InsertEndChild(userNode);
return doc.SaveFile(xmlPath);
}
void loadXML(const char* xmlPath) {
XMLDocument doc;
if (doc.LoadFile(xmlPath) != XML_SUCCESS) {
std::cout << "load xlm file failed" << std::endl;
return;
}
XMLPrinter printer;
doc.Print( &printer);
std::cout << printer.CStr();
}
//添加性别,号码,邮箱 再添加一个用户
int addXML1(const char* xmlPath) {
XMLDocument doc;
if (doc.LoadFile(xmlPath) != XML_SUCCESS) {
std::cout << "load xlm file failed" << std::endl;
return -1;
}
XMLElement *root = doc.RootElement();
XMLElement *userNode = root->FirstChildElement("User");
XMLElement *gender = doc.NewElement("Gender");
XMLText* genderText = doc.NewText("man");
gender->InsertFirstChild(genderText);
userNode->InsertFirstChild(gender);
XMLElement *mobile = doc.NewElement("Mobile");
mobile->InsertFirstChild(doc.NewText("186****3143"));
userNode->InsertEndChild(mobile);
XMLElement *email = doc.NewElement("Email");
email->InsertFirstChild(doc.NewText("[email protected]"));
userNode->InsertEndChild(email);
XMLElement *userNode2 = doc.NewElement("User");
userNode2->SetAttribute("Name", "king");
userNode2->SetAttribute("Password", "pwd2");
root->InsertEndChild(userNode2);
XMLElement *mobile2 = doc.NewElement("Mobile");
mobile2->InsertFirstChild(doc.NewText("186****3143"));
userNode2->InsertEndChild(mobile2);
return doc.SaveFile(xmlPath);
}
//在性别后面添加年龄,再添加一个号码
int addXML2(const char* xmlPath)
{
XMLDocument doc;
if (doc.LoadFile(xmlPath) != XML_SUCCESS)
{
std::cout<<"load xml file failed"<FirstChildElement("User");
XMLElement* gender = userNode->FirstChildElement("Gender");
XMLElement* age = doc.NewElement("Age");
age->InsertFirstChild(doc.NewText("18"));
userNode->InsertAfterChild(gender,age);
XMLElement* mobile = userNode->FirstChildElement("Mobile");
mobile->SetAttribute("Location","home");
XMLElement* mobile1 = doc.NewElement("Mobile");
mobile1->SetAttribute("Location","company");
mobile1->InsertFirstChild(doc.NewText("186****3143"));
userNode->InsertAfterChild(mobile, mobile1);
return doc.SaveFile(xmlPath);
}
//删除第一个号码,删除第二个号码的属性
int deleteXML(const char* xmlPath) {
XMLDocument doc;
if (doc.LoadFile(xmlPath) != XML_SUCCESS) {
std::cout << "load xlm file failed" << std::endl;
return -1;
}
XMLElement *root = doc.RootElement();
XMLElement *userNode = root->FirstChildElement("User");
XMLElement *mobile = userNode->FirstChildElement("Mobile");
userNode->DeleteChild(mobile);
XMLElement *mobile2 = userNode->FirstChildElement("Mobile");
mobile2->DeleteAttribute("Location");
return doc.SaveFile(xmlPath);
}
//将milo的年龄改为10000岁,将king的号码改为8888结尾
int updateXML(const char* xmlPath) {
XMLDocument doc;
if (doc.LoadFile(xmlPath) != XML_SUCCESS) {
std::cout << "load xlm file failed" << std::endl;
return -1;
}
XMLElement *root = doc.RootElement();
XMLElement *userNode = root->FirstChildElement("User");
while (userNode != NULL) {
if (0 == strncmp("milo", (userNode->Attribute("Name")), 11)) {
userNode->FirstChildElement("Age")->SetText("10000");
userNode = userNode->NextSiblingElement();
} else if (0 == strncmp("king", (userNode->Attribute("Name")), 11)) {
userNode->FirstChildElement("Mobile")->SetText("186****8888");
userNode = userNode->NextSiblingElement();
} else {
userNode = userNode->NextSiblingElement();
}
}
return doc.SaveFile(xmlPath);
}
//将milo的信息打印出来
int selectXML(const char* xmlPath)
{
XMLDocument doc;
if(doc.LoadFile(xmlPath)!=XML_SUCCESS)
{
std::cout<<"load xml file failed"<FirstChildElement("User");
while(userNode != NULL)
{
if( 0 == strncmp("milo",(userNode->Attribute("Name")),11))
{
std::cout << userNode->Attribute("Name") << std::endl;
std::cout << userNode->Attribute("Password") << std::endl;
std::cout << userNode->FirstChildElement("Age")->GetText() << std::endl;
std::cout << userNode->FirstChildElement("Gender")->GetText() << std::endl;
std::cout << userNode->FirstChildElement("Mobile")->GetText() << std::endl;
std::cout << userNode->FirstChildElement("Email")->GetText() << std::endl;
userNode = userNode->NextSiblingElement();
} else {
userNode = userNode->NextSiblingElement();
}
}
return 0;
}
int main( int argc, const char ** argv )
{
char xmlPath[] = "./0voice.xml";
/*创建*/
createXML(xmlPath);
loadXML(xmlPath);
printf("------------------------------\n");
/*增*/
addXML1(xmlPath);
loadXML(xmlPath);
printf("------------------------------\n");
addXML2(xmlPath);
loadXML(xmlPath);
printf("------------------------------\n");
/*删*/
deleteXML(xmlPath);
loadXML(xmlPath);
printf("------------------------------\n");
/*改*/
updateXML(xmlPath);
loadXML(xmlPath);
printf("------------------------------\n");
/*查*/
selectXML(xmlPath);
return 0;
}
#include
#include "tinyxml2.h"
#define CHECK_TINYXML2_RESULT(ret) \
do \
{ \
if (ret != tinyxml2::XML_SUCCESS) \
{ \
std::cout << __FUNCTION__ << "(" << __LINE__ << ") failed, ret = " << ret << std::endl; \
return -1; \
} \
} while (0)
/**
* @brief: 写相机属性. 产生完了之后将所有节点挂在p下面
* @param p 某个相机节点
* @param doc 所有的元素属性以及值均在doc的下面
* @param ipAddr IP地址
* @return: 返回说明
* @retval: 返回值说明
*/
static void WriteOneCameraAttibute(tinyxml2::XMLElement *p, tinyxml2::XMLDocument &doc,
const char *ipAddr)
{
const char *subnetMask = "123.45.67.89";
tinyxml2::XMLElement *pDevID = doc.NewElement("DevID");
tinyxml2::XMLText *pDevIdText = doc.NewText("5");
pDevID->InsertEndChild(pDevIdText);
p->InsertEndChild(pDevID);
tinyxml2::XMLElement *pIpAddr = doc.NewElement("IpAddress");
tinyxml2::XMLText *pIpAddrText = doc.NewText(ipAddr);
pIpAddr->InsertEndChild(pIpAddrText);
p->InsertEndChild(pIpAddr);
tinyxml2::XMLElement *pSubnetMask = doc.NewElement("SubnetMask");
tinyxml2::XMLText *pSubnetMaskText = doc.NewText(subnetMask);
pSubnetMask->InsertEndChild(pSubnetMaskText);
p->InsertEndChild(pSubnetMask);
tinyxml2::XMLElement *pExposureAuto = doc.NewElement("ExposureAuto");
tinyxml2::XMLText *pExposureAutoText = doc.NewText("false");
pExposureAuto->InsertEndChild(pExposureAutoText);
p->InsertEndChild(pExposureAuto);
tinyxml2::XMLElement *pExposureTime = doc.NewElement("ExposureTime");
tinyxml2::XMLText *pExposureTimeText = doc.NewText("200");
pExposureTime->InsertEndChild(pExposureTimeText);
p->InsertEndChild(pExposureTime);
tinyxml2::XMLElement *pTriggerMode = doc.NewElement("TriggerMode");
tinyxml2::XMLText *pTriggerModeText = doc.NewText("false");
pTriggerMode->InsertEndChild(pTriggerModeText);
p->InsertEndChild(pTriggerMode);
}
/**
* @brief: 将数据写到某个xml文件中
* @param path xml文件路径
* @return: 返回说明
* @retval: 返回值说明
*/
static int WriteParam(const std::string &path)
{
tinyxml2::XMLError ret;
tinyxml2::XMLDocument doc;
const char *declaration = "";
ret = doc.Parse(declaration);
CHECK_TINYXML2_RESULT(ret);
tinyxml2::XMLElement *pFirst = doc.NewElement("CameraI");
pFirst->SetAttribute("type", "home");
pFirst->SetAttribute("price", 1000);
pFirst->SetAttribute("wifi", true);
// 内部插内容
WriteOneCameraAttibute(pFirst, doc, "1.22.32.82");
doc.InsertEndChild(pFirst);
tinyxml2::XMLElement *pSecond = doc.NewElement("CameraII");
// 内部插内容
WriteOneCameraAttibute(pSecond, doc, "2.22.32.82");
doc.InsertEndChild(pSecond);
tinyxml2::XMLElement *pThree = doc.NewElement("CameraIII");
// 内部插内容
WriteOneCameraAttibute(pThree, doc, "3.22.32.82");
doc.InsertEndChild(pThree);
ret = doc.SaveFile(path.c_str());
return 0;
}
/**
* @brief: 读取每个相机的属性
* @param p 相机节点指针
* @return: 返回说明
* @retval: 返回值说明
*/
static void ReadOneCameraAttribute(const tinyxml2::XMLElement *p)
{
int devIdContent = p->FirstChildElement("DevID")->IntText();
const char *ipAddrContent = p->FirstChildElement("IpAddress")->GetText();
const char *subnetMaskContent = p->FirstChildElement("SubnetMask")->GetText();
const char *exposureAutoContent = p->FirstChildElement("ExposureAuto")->GetText();
int64_t exposureTimeContent = p->FirstChildElement("ExposureTime")->Int64Text();
bool triggerModeContent = p->FirstChildElement("TriggerMode")->BoolText();
std::cout << "devIdContent(int):\t" << devIdContent << std::endl;
std::cout << "ipAddrContent:\t" << ipAddrContent << std::endl;
std::cout << "subnetMaskContent:\t" << subnetMaskContent << std::endl;
std::cout << "exposureAutoContent:\t" << exposureAutoContent << std::endl;
std::cout << "exposureTimeContent(int64_t):\t" << exposureTimeContent << std::endl;
std::cout << "triggerModeContent(bool):\t" << ((triggerModeContent == true) ? "true" : "false") << std::endl;
}
/**
* @brief: 读取解析某路径的xml文件
* @param path xml文件路径
* @return: 返回说明
* @retval: 返回值说明
*/
static int ReadParam(const std::string &path)
{
// 导入文件错误, 退出
tinyxml2::XMLDocument doc;
tinyxml2::XMLError error = doc.LoadFile(path.c_str());
CHECK_TINYXML2_RESULT(error);
tinyxml2::XMLElement *pFirst = doc.FirstChildElement("CameraI"); //doc.RootElement();// 等同
tinyxml2::XMLElement *pSecond = doc.FirstChildElement("CameraII");
tinyxml2::XMLElement *pThree = doc.FirstChildElement("CameraIII");
// 分别读取每个相机的各个属性
ReadOneCameraAttribute(pFirst);
std::cout << "------------------\n";
ReadOneCameraAttribute(pSecond);
std::cout << "------------------\n";
ReadOneCameraAttribute(pThree);
std::cout << "------------------\n";
return 0;
}
/**
* @brief: 修改相机属性
* @param p 相机节点指针
* @return: 返回说明
* @retval: 返回值说明
*/
static void ModifyOneCamera(tinyxml2::XMLElement *p)
{
int devId = 4;
const char *ipAddr = "139.66.38.13";
const char *subnetMask = "255.0.0.0";
bool exposureAuto = false;
int64_t exposureTime = 80;
bool triggerMode = false;
p->FirstChildElement("DevID")->SetText(devId);
p->FirstChildElement("IpAddress")->SetText(ipAddr);
p->FirstChildElement("SubnetMask")->SetText(subnetMask);
p->FirstChildElement("ExposureAuto")->SetText(exposureAuto);
p->FirstChildElement("ExposureTime")->SetText(exposureTime);
p->FirstChildElement("TriggerMode")->SetText(triggerMode);
}
/**
* @brief: 修改某xml文件的参数
* @param path xml文件路径
* @return: 返回说明
* @retval: 返回值说明
*/
static void ModifyParam(const std::string &path)
{
// 导入文件错误, 退出
tinyxml2::XMLDocument doc;
tinyxml2::XMLError error = doc.LoadFile(path.c_str());
if (error != tinyxml2::XMLError::XML_SUCCESS)
return;
// 三个相机指针
tinyxml2::XMLElement *pFirst = doc.FirstChildElement("CameraI");
tinyxml2::XMLElement *pSecond = doc.FirstChildElement("CameraII");
tinyxml2::XMLElement *pThree = doc.FirstChildElement("CameraIII");
// 修改
ModifyOneCamera(pFirst);
ModifyOneCamera(pSecond);
ModifyOneCamera(pThree);
doc.SaveFile(path.c_str());
}
void testCameraXML()
{
std::string path = "camera_info_2.xml";
std::cout << "---------------生成一个xml文件------------------" << std::endl;
WriteParam(path);
std::cout << "--------------写文件结束,读取生成的xml文件------------------" << std::endl;
ReadParam(path);
std::cout << "--------------读文件结束,修改文件开始------------------" << std::endl;
ModifyParam(path);
std::cout << "--------------修改文件结束,读取修改的xml文件------------------" << std::endl;
ReadParam(path);
}
int main(void)
{
testCameraXML();
return 0;
}
#include
#include "tinyxml2.h"
#define CHECK_TINYXML2_RESULT(ret) \
do \
{ \
if (ret != tinyxml2::XML_SUCCESS) \
{ \
std::cout << __FUNCTION__ << "(" << __LINE__ << ") failed, ret = " << ret << std::endl; \
return -1; \
} \
} while (0)
typedef struct cameraInfo
{
int id;
std::string type;
std::string ipAddr;
std::string subnetMask;
bool exposureAuto;
int64_t exposureTime;
bool triggerMode;
float price;
} CAMERA_INFO_T;
/**
* @brief: 写入类型1 Camera的测试信息
* @param p
* @param doc
* @return: 返回说明
* @retval: 返回值说明
*/
static void WriteCameraI(tinyxml2::XMLElement *p, tinyxml2::XMLDocument &doc)
{
const char *ipAddr = "178.26.85.83";
const char *subnetMask = "123.45.67.89";
// 1. 创建一个CameraI
tinyxml2::XMLElement *cameraI_1 = doc.NewElement("CameraI");
// 2. 封装CameraI
// 写入属性
cameraI_1->SetAttribute("type", "home");
cameraI_1->SetAttribute("id", 5);
// 写入IP地址
tinyxml2::XMLElement *pIpAddr = doc.NewElement("IpAddress");
tinyxml2::XMLText *pIpAddrText = doc.NewText(ipAddr);
pIpAddr->InsertEndChild(pIpAddrText);
cameraI_1->InsertEndChild(pIpAddr);
// 写入子网掩码
tinyxml2::XMLElement *pSubnetMask = doc.NewElement("SubnetMask");
tinyxml2::XMLText *pSubnetMaskText = doc.NewText(subnetMask);
pSubnetMask->InsertEndChild(pSubnetMaskText);
cameraI_1->InsertEndChild(pSubnetMask);
// 写入是否自动曝光
tinyxml2::XMLElement *pExposureAuto = doc.NewElement("ExposureAuto");
tinyxml2::XMLText *pExposureAutoText = doc.NewText("false");
pExposureAuto->InsertEndChild(pExposureAutoText);
cameraI_1->InsertEndChild(pExposureAuto);
// 写入曝光时长
tinyxml2::XMLElement *pExposureTime = doc.NewElement("ExposureTime");
tinyxml2::XMLText *pExposureTimeText = doc.NewText("200");
pExposureTime->InsertEndChild(pExposureTimeText);
cameraI_1->InsertEndChild(pExposureTime);
// 写入触发模式
tinyxml2::XMLElement *pTriggerMode = doc.NewElement("TriggerMode");
tinyxml2::XMLText *pTriggerModeText = doc.NewText("false");
pTriggerMode->InsertEndChild(pTriggerModeText);
cameraI_1->InsertEndChild(pTriggerMode);
// 写入价格
tinyxml2::XMLElement *pPrice = doc.NewElement("Price");
tinyxml2::XMLText *pPriceText = doc.NewText("9.9");
pPrice->InsertEndChild(pPriceText);
cameraI_1->InsertEndChild(pPrice);
// 3. 将一个CameraI插入到CameraConfig
p->InsertEndChild(cameraI_1);
// 1. 创建一个CameraI
tinyxml2::XMLElement *cameraI_2 = doc.NewElement("CameraI");
// 2. 封装CameraI
// 写入属性
cameraI_2->SetAttribute("type", "company");
cameraI_2->SetAttribute("id", 6);
// 写入IP地址
pIpAddr = doc.NewElement("IpAddress");
pIpAddrText = doc.NewText(ipAddr);
pIpAddr->InsertEndChild(pIpAddrText);
cameraI_2->InsertEndChild(pIpAddr);
// 写入子网掩码
pSubnetMask = doc.NewElement("SubnetMask");
pSubnetMaskText = doc.NewText(subnetMask);
pSubnetMask->InsertEndChild(pSubnetMaskText);
cameraI_2->InsertEndChild(pSubnetMask);
// 写入是否自动曝光
pExposureAuto = doc.NewElement("ExposureAuto");
pExposureAutoText = doc.NewText("false");
pExposureAuto->InsertEndChild(pExposureAutoText);
cameraI_2->InsertEndChild(pExposureAuto);
// 写入曝光时长
pExposureTime = doc.NewElement("ExposureTime");
pExposureTimeText = doc.NewText("200");
pExposureTime->InsertEndChild(pExposureTimeText);
cameraI_2->InsertEndChild(pExposureTime);
// 写入触发模式
pTriggerMode = doc.NewElement("TriggerMode");
pTriggerModeText = doc.NewText("false");
pTriggerMode->InsertEndChild(pTriggerModeText);
cameraI_2->InsertEndChild(pTriggerMode);
// 写入价格
// 3. 将一个CameraI插入到CameraConfig
p->InsertEndChild(cameraI_2);
}
/**
* @brief: 写入类型2 Camera的测试信息
* @param p
* @param doc
* @return: 返回说明
* @retval: 返回值说明
*/
static void WriteCameraII(tinyxml2::XMLElement *p, tinyxml2::XMLDocument &doc)
{
const char *ipAddr = "2.26.85.83";
const char *subnetMask = "123.45.67.89";
// 1. 创建一个CameraII
tinyxml2::XMLElement *cameraII_1 = doc.NewElement("CameraII");
// 2. 封装CameraII
// 写入设备ID
tinyxml2::XMLElement *pDevID = doc.NewElement("DevID");
tinyxml2::XMLText *pDevIdText = doc.NewText("7");
pDevID->InsertEndChild(pDevIdText);
cameraII_1->InsertEndChild(pDevID);
// 写入IP地址
tinyxml2::XMLElement *pIpAddr = doc.NewElement("IpAddress");
tinyxml2::XMLText *pIpAddrText = doc.NewText(ipAddr);
pIpAddr->InsertEndChild(pIpAddrText);
cameraII_1->InsertEndChild(pIpAddr);
// 写入子网掩码
tinyxml2::XMLElement *pSubnetMask = doc.NewElement("SubnetMask");
tinyxml2::XMLText *pSubnetMaskText = doc.NewText(subnetMask);
pSubnetMask->InsertEndChild(pSubnetMaskText);
cameraII_1->InsertEndChild(pSubnetMask);
// 写入是否自动曝光
tinyxml2::XMLElement *pExposureAuto = doc.NewElement("ExposureAuto");
tinyxml2::XMLText *pExposureAutoText = doc.NewText("false");
pExposureAuto->InsertEndChild(pExposureAutoText);
cameraII_1->InsertEndChild(pExposureAuto);
// 写入曝光时长
tinyxml2::XMLElement *pExposureTime = doc.NewElement("ExposureTime");
tinyxml2::XMLText *pExposureTimeText = doc.NewText("200");
pExposureTime->InsertEndChild(pExposureTimeText);
cameraII_1->InsertEndChild(pExposureTime);
// 写入触发模式
tinyxml2::XMLElement *pTriggerMode = doc.NewElement("TriggerMode");
tinyxml2::XMLText *pTriggerModeText = doc.NewText("false");
pTriggerMode->InsertEndChild(pTriggerModeText);
cameraII_1->InsertEndChild(pTriggerMode);
// 写入价格
tinyxml2::XMLElement *pPrice = doc.NewElement("Price");
tinyxml2::XMLText *pPriceText = doc.NewText("9.9");
pPrice->InsertEndChild(pPriceText);
cameraII_1->InsertEndChild(pPrice);
// 3. 将一个CameraI插入到CameraConfig
p->InsertEndChild(cameraII_1);
// 1. 创建一个CameraII
tinyxml2::XMLElement *cameraII_2 = doc.NewElement("CameraII");
// 2. 封装CameraII
// 写入设备ID
pDevID = doc.NewElement("DevID");
pDevIdText = doc.NewText("8");
pDevID->InsertEndChild(pDevIdText);
cameraII_2->InsertEndChild(pDevID);
// 写入IP地址
pIpAddr = doc.NewElement("IpAddress");
pIpAddrText = doc.NewText(ipAddr);
pIpAddr->InsertEndChild(pIpAddrText);
cameraII_2->InsertEndChild(pIpAddr);
// 写入子网掩码
pSubnetMask = doc.NewElement("SubnetMask");
pSubnetMaskText = doc.NewText(subnetMask);
pSubnetMask->InsertEndChild(pSubnetMaskText);
cameraII_2->InsertEndChild(pSubnetMask);
// 写入是否自动曝光
pExposureAuto = doc.NewElement("ExposureAuto");
pExposureAutoText = doc.NewText("false");
pExposureAuto->InsertEndChild(pExposureAutoText);
cameraII_2->InsertEndChild(pExposureAuto);
// 写入曝光时长
pExposureTime = doc.NewElement("ExposureTime");
pExposureTimeText = doc.NewText("400");
pExposureTime->InsertEndChild(pExposureTimeText);
cameraII_2->InsertEndChild(pExposureTime);
// 写入触发模式
pTriggerMode = doc.NewElement("TriggerMode");
pTriggerModeText = doc.NewText("false");
pTriggerMode->InsertEndChild(pTriggerModeText);
cameraII_2->InsertEndChild(pTriggerMode);
// 写入价格
// 3. 将一个CameraI插入到CameraConfig
p->InsertEndChild(cameraII_2);
}
/**
* @brief: 写入类型Camera的测试信息
* @param path 路径
* @return: 返回说明
* @retval: 返回值说明
*/
static int WriteXML(const std::string &path)
{
tinyxml2::XMLError ret;
tinyxml2::XMLDocument doc;
const char *declaration = "";
ret = doc.Parse(declaration);
CHECK_TINYXML2_RESULT(ret);
tinyxml2::XMLElement *root = doc.NewElement("CameraConfig");
root->SetAttribute("version", "1.0");
WriteCameraI(root, doc);
WriteCameraII(root, doc);
doc.InsertEndChild(root); // InsertEndChild 添加节点
ret = doc.SaveFile(path.c_str());
CHECK_TINYXML2_RESULT(ret);
return 0;
}
/**
* @brief: 读取一个camera信息
* @param {type} 形参 参数说明
* @return: 返回说明
* @retval: 返回值说明
*/
static void ReadOneCameraXML(const tinyxml2::XMLElement *p)
{
std::cout << "Model:" << p->Name() << std::endl;
const tinyxml2::XMLAttribute *type = p->FindAttribute("type");
if (type)
{
std::cout << "camera type:\t" << type->Value() << std::endl;
}
const tinyxml2::XMLAttribute *id = p->FindAttribute("id");
if (id)
{
std::cout << "camera id:\t" << id->IntValue() << std::endl;
}
const tinyxml2::XMLElement *devId = p->FirstChildElement("DevID");
if (devId) // 判断某个元素是否存在
{
int devIdContent = devId->IntText();
std::cout << "devIdContent(int):\t" << devIdContent << std::endl;
}
const char *ipAddrContent = p->FirstChildElement("IpAddress")->GetText();
const char *subnetMaskContent = p->FirstChildElement("SubnetMask")->GetText();
const char *exposureAutoContent = p->FirstChildElement("ExposureAuto")->GetText();
int64_t exposureTimeContent = p->FirstChildElement("ExposureTime")->Int64Text();
bool triggerModeContent = p->FirstChildElement("TriggerMode")->BoolText();
std::cout << "ipAddrContent:\t" << ipAddrContent << std::endl;
std::cout << "subnetMaskContent:\t" << subnetMaskContent << std::endl;
std::cout << "exposureAutoContent:\t" << exposureAutoContent << std::endl;
std::cout << "exposureTimeContent(int64_t):\t" << exposureTimeContent << std::endl;
std::cout << "triggerModeContent(bool):\t" << ((triggerModeContent == true) ? "true" : "false") << std::endl;
const tinyxml2::XMLElement *pPrice = p->FirstChildElement("Price");
if (pPrice) // 判断某个元素是否存在
{
std::cout << "price(float):\t" << pPrice->FloatText() << std::endl;
}
}
/**
* @brief: 遍历XML
* @param path 本地文件路径
* @return: 返回说明
* @retval: 返回值说明
*/
static int ParseXML(const std::string &path)
{
std::cout << "ParseXML into" << std::endl;
tinyxml2::XMLDocument doc;
tinyxml2::XMLError error = doc.LoadFile(path.c_str());
CHECK_TINYXML2_RESULT(error); // 如果错误则退出
std::cout << "ParseXML:" << std::endl;
tinyxml2::XMLElement *root = doc.RootElement();
tinyxml2::XMLElement *element = NULL;
element = root->FirstChildElement();
while (true)
{
if (element)
{
std::cout << "-------------------------------------" << std::endl;
ReadOneCameraXML(element);
}
else
{
std::cout << "-------------------------------------" << std::endl;
std::cout << "ParseXML finish" << std::endl;
break;
}
element = element->NextSiblingElement();
}
return 0;
}
/**
* @brief: 修改一个CameraI
* @param {type} 形参 参数说明
* @return: 返回说明
* @retval: 返回值说明
*/
static void ModifyOneCameraById(tinyxml2::XMLElement *root, tinyxml2::XMLDocument &doc, const CAMERA_INFO_T &cameraInfo)
{
tinyxml2::XMLElement *element = NULL;
element = root->FirstChildElement();
bool isFindId = false;
while (true)
{
if (element)
{
const tinyxml2::XMLAttribute *id = element->FindAttribute("id");
if (id)
{
std::cout << "current id:\t" << id->IntValue() << std::endl;
if (id->IntValue() == cameraInfo.id)
{
std::cout << "Find id:\t" << id->IntValue() << std::endl;
isFindId = true;
break;
}
}
const tinyxml2::XMLElement *devId = element->FirstChildElement("DevID");
if (devId) // 判断某个元素是否存在
{
std::cout << "current id:\t" << id->IntValue() << std::endl;
if (id->IntValue() == cameraInfo.id)
{
std::cout << "Find id:\t" << id->IntValue() << std::endl;
isFindId = true;
break;
}
}
}
else
{
std::cout << "-------------------------------------" << std::endl;
std::cout << "Find XML finish, not find id:\t" << cameraInfo.id << std::endl;
break;
}
// element = root->NextSiblingElement();
std::cout << "----------NextSiblingElement------------" << std::endl;
element = element->NextSiblingElement(); // 兄弟节点
}
if (isFindId)
{
std::cout << "isFindId: " << isFindId << std::endl;
std::cout << "ipAddr: " << cameraInfo.ipAddr.c_str() << std::endl;
element->FirstChildElement("IpAddress")->SetText(cameraInfo.ipAddr.c_str());
element->FirstChildElement("SubnetMask")->SetText(cameraInfo.subnetMask.c_str());
element->FirstChildElement("ExposureAuto")->SetText(cameraInfo.exposureAuto);
element->FirstChildElement("ExposureTime")->SetText(cameraInfo.exposureTime);
element->FirstChildElement("TriggerMode")->SetText(cameraInfo.triggerMode);
element->SetAttribute("type", cameraInfo.type.c_str());
tinyxml2::XMLElement *pPrice = element->FirstChildElement("Price");
if (pPrice)
{
pPrice->SetText(cameraInfo.price);
}
else // 查找失败则说明没有该属性,需要添加
{
pPrice = doc.NewElement("Price");
char cpriceBuf[20];
sprintf(cpriceBuf, "%0.2f", cameraInfo.price);
std::cout << " Add price: " << cpriceBuf << std::endl;
tinyxml2::XMLText *pPriceText = doc.NewText(cpriceBuf);
tinyxml2::XMLComment *pPriceComment = doc.NewComment("add price");
element->InsertEndChild(pPriceComment);
pPrice->InsertEndChild(pPriceText);
element->InsertEndChild(pPrice);
}
}
}
/**
* @brief: 修改指定ID的camera的参数
* @param path 路径
* @param camearInfo 新的参数信息
* @return: 返回说明
* @retval: 返回值说明
*/
static int ModifyXMLById(const std::string &path, const CAMERA_INFO_T &camearInfo)
{
// 导入文件错误, 退出
tinyxml2::XMLDocument doc;
tinyxml2::XMLError error = doc.LoadFile(path.c_str());
CHECK_TINYXML2_RESULT(error);
tinyxml2::XMLElement *root = doc.FirstChildElement("CameraConfig");
ModifyOneCameraById(root, doc, camearInfo);
error = doc.SaveFile(path.c_str());
CHECK_TINYXML2_RESULT(error);
return 0;
}
void testCameraXML()
{
std::string path = "camera_config_1.xml";
// // std::string path = "camera_info.xml";
std::cout << "---------------生成一个xml文件------------------" << std::endl;
WriteXML(path);
std::cout << "--------------写文件结束,读取生成的xml文件------------------" << std::endl;
ParseXML(path);
std::cout << "--------------读文件结束,根据ID查找camera并修改--------------" << std::endl;
CAMERA_INFO_T cameraInfo;
cameraInfo.id = 6;
cameraInfo.type = "hotel";
cameraInfo.ipAddr = "111.26.85.8";
cameraInfo.subnetMask = "111.26.85.255";
cameraInfo.exposureAuto = true;
cameraInfo.triggerMode = false;
cameraInfo.price = 100;
ModifyXMLById(path, cameraInfo);
std::cout << "--------------修改文件结束,读取修改的xml文件------------------" << std::endl;
ParseXML(path);
}
int main(void)
{
testCameraXML();
return 0;
}
#此处直接是引用tinyxml2.cpp tinyxml2.h,把这二个文件copy到当前目录
g++ tinyxml2.cpp tinyxml2.h demo01.cpp -o demo01 -std=c++11
g++ tinyxml2.cpp tinyxml2.h demo02.cpp -o demo02 -std=c++11
g++ tinyxml2.cpp tinyxml2.h demo03.cpp -o demo03 -std=c++11
g++ tinyxml2.cpp tinyxml2.h demo04.cpp -o demo04 -std=c++11
g++ tinyxml2.cpp tinyxml2.h demo05.cpp -o demo05 -std=c++11