- TinyXml2 库使用方法
下载地址 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。
XMLAttribute 是解析 XML 的属性的类,XML 中的属性都与 XML 的 Element 绑定,并且为 key-value 类型。
XMLComment 主要是处理 XML 注释的类,注释的存储形式为""。
XMLDeclaration 主要是处理 XML 中声明的类,声明的存储形式为"<? declaration ?>"。 XMLDocument 代表 XML 整个实体,TinyXML2 中只有 XMLDocument 类可以被实例化,其他的类必
须通过 XMLDocument 提供的 new 方法进行实例化,而不能直接实例化。XMLNode
的其他实体类把构造函数定义为 protected,不能被外部实例化,这样保证使用 XMLDocument 进行内存的管理,避免产生内存泄漏的风险。
XMLElement XMLElement 类是 XMLNode 中最重要的一个类,其存储方式有<foo/>和<foo></foo> 两 种 形 式 , 它 包 含 了 一 个 XMLAttribute 的 根 指 针 , 这 个 root 指 针 指 向 XMLAttribute 的第一个属性键值对。
XMLHandle 主要用来访问元素。
XMLNode 是几乎 XML 所有元素(XMLAttribute 除外)的基类,XML 本质是一种树形结构,而 整个 XML 就是由许多的节点(XMLNode)组成,在 TinyXML2 中每个 XMLNode 节点都 保存了父亲、前驱、后继、孩子头节点和孩子尾节点信息,便于查询、插入、检 索。
XMLPrinter 是 XMLVisitor 类的子类,主要实现的写 XML 的功能,其提供了两种书写方式,一 是构建 XMLDocument,二是直接 push 字段。
XMLText 主要是处理 XML 文本的类,文本信息又分为 CDATA 和普通文本。CDATA 是有专属的 开始字符"<![CDATA[",而普通的文本存储形式如">text<"。
XMLUnknown 存储形式为"<! unknown>"。
XMLVisitor 访问者模式的基类,它主要定义了访问者的接口,而在 XMLNode 的子类的 accept 方法中调用这些方法来完成对自身的访问。
#include <iostream>
#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 <iostream>
#include "tinyxml2.h"
int main(void)
{
const char *xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \
<note> \
<to>beijing</to> \
<from>shenzhen</from> \
<heading>Reminder</heading> \
<body>Don't forget the meeting!</body> \
</note>";
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 <iostream>
#include "tinyxml2.h"
#include <stdio.h>
#include <stdlib.h>
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;
}
//添加声明 <?xml version="1.0" encoding="UTF-8" ?>
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("472251823@qq.com"));
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"<<std::endl;
return false;
}
XMLElement* root=doc.RootElement();
XMLElement* userNode=root->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"<<std::endl;
return false;
}
XMLElement* root=doc.RootElement();
XMLElement* userNode=root->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 <iostream>
#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 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
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 <iostream>
#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 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
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