大家好,又见面了,我是你们的朋友全栈君。
RapidXml是指 XML DOM解析工具包,是一个快速的读写xml文件的库文件(hpp)。本文旨在提供RapidXml文件读写操作,以及对节点的增加、删除、编译提供一个测试用例,以免忘记。
1. 读取XML
#include "rapidxml.hpp"
#include "rapidxml_utils.hpp"
#include "rapidxml_print.hpp"
#include <vector>
#include <string>
#include <map>
#include <set>
#include <iostream>
#include <sstream>
#include <io.h>
void str2int(int& int_tmp, const std::string& string_tmp)
{
std::stringstream stream(string_tmp);
stream >> int_tmp;
}
void str2float(float& float_tmp, const std::string& string_tmp)
{
float_tmp = atof(string_tmp.c_str());
}
void splitLabels(const std::string& labels, std::vector<std::string>& splitalbelres)
{
std::string result;
std::stringstream input(labels);
while (input >> result)
{
splitalbelres.push_back(result);
}
}
void readFunctionParam(rapidxml::xml_node<char>* FunctionNode)
{
rapidxml::xml_node<char>* DeteNode = FunctionNode->first_node("Detectors");
if (DeteNode != nullptr)
{
for (rapidxml::xml_node<char>* node = DeteNode->first_node("iter"); node != nullptr; node = node->next_sibling())
{
std::string name = "";
std::string version = "";
std::string label = "";
float fConfidence = 0.0;
int iShowWin = 0;
int iIsStandard = 0;
std::set<int> setUsefulLabel;
rapidxml::xml_node<>* pName = node->first_node("name");
if (pName != nullptr)
{
name = pName->value();
}
rapidxml::xml_node<>* pVersion = node->first_node("version");
if (pVersion != nullptr)
{
version = pVersion->value();
}
rapidxml::xml_node<>* pConf = node->first_node("confidence");
if (pConf != nullptr)
{
str2float(fConfidence, pConf->value());
}
rapidxml::xml_node<>* pShowWin = node->first_node("bshowDebugWin");
if (pShowWin != nullptr)
{
str2int(iShowWin, pShowWin->value());
}
rapidxml::xml_node<>* pIsStandard = node->first_node("bStandard");
if (pIsStandard != nullptr)
{
str2int(iIsStandard, pIsStandard->value());
}
rapidxml::xml_node<>* pUsefulLabel = node->first_node("usefulLabel");
if (pUsefulLabel != nullptr)
{
label = pUsefulLabel->value();
std::vector<std::string> splitlabelres;
splitLabels(label, splitlabelres);
for (int i = 0; i < splitlabelres.size(); i++)
{
setUsefulLabel.insert(std::atoi(splitlabelres[i].c_str()));
}
}
}
rapidxml::xml_node<char>* pShowreportNode = FunctionNode->first_node("ShowReportWin");
if (pShowreportNode != nullptr)
{
int iShowReportWin = 0;
str2int(iShowReportWin, pShowreportNode->value());
}
}
}
void ReadParam(const rapidxml::xml_document<>& pDoc)
{
//获取根节点
rapidxml::xml_node<char>* root = pDoc.first_node("config");
//找到采样帧率节点
int iSampleFrequency;
rapidxml::xml_node<>* samplefre = root->first_node("SampleFrequency");
str2int(iSampleFrequency, samplefre->value());
//找到功能节点
std::string sFunctionName = "SMOKEFireDetection";
rapidxml::xml_node<>* intrusion = root->first_node(sFunctionName.c_str());
if (intrusion != nullptr)
{
readFunctionParam(intrusion);
}
}
void readXMLByFile(const std::string& xmlpath)
{
/************************************************************************
file类
data() 返回 char* 的xml文本内容
size() 返回 unsigned int的文本数据长度
定义: rapidxml::file<0> valName("xmlpath");
xml_document类
parse(Ch *text) 将文本数据解析为DOM tree
clear() 清空DOM tree
定义: rapidxml::xml_document<0> doc;
************************************************************************/
try
{
// 用file文件读入缓冲区
rapidxml::file<> fdoc(xmlpath.c_str());
// 打印从文件中读取的内容
std::cout << fdoc.data();
// 解析获取DOM实例
rapidxml::xml_document<> doc;
doc.parse<0>(fdoc.data());
ReadParam(doc);
doc.clear();
}
catch (rapidxml::parse_error e)
{
std::cout << e.what() << std::endl;
return;
}
}
static const int buf_len = 2048;
static char buf[buf_len] = { 0 };
void readXMLByStream(const std::string& xmlpath)
{
try
{
// 清空缓冲区
memset(buf, 0, buf_len);
// 判断文件是否存在
if (_access(xmlpath.c_str(), 0) == -1)
{
std::cout << "xml file " << xmlpath << "is not exits!" << std::endl;
return;
}
// 实例化文件读取流
std::ifstream infile(xmlpath, std::ios::in);
if (!infile)
{
std::cout << "file stream instance error!" << std::endl;
return;
}
// 读取文件内容到缓冲区
infile.read(buf, buf_len);
// 输出文件内容
std::cout << buf << std::endl;
// 实例化DOM
rapidxml::xml_document<> doc;
doc.parse<0>(buf);
ReadParam(doc);
doc.clear();
infile.close();
}
catch (rapidxml::parse_error e)
{
std::cout << e.what() << std::endl;
return;
}
}
void main()
{
std::string xmlpath = "ReadExample.xml";
readXMLByFile(xmlpath);
readXMLByStream(xmlpath);
std::system("pause");
}
其对应的xml文件如下所示:
<config>
<SampleFrequency>25</SampleFrequency>
<SMOKEFireDetection>
<Detectors>
<iter>
<name>fire</name>
<version>1.3.0</version>
<confidence>0.5</confidence>
<bshowDebugWin>1</bshowDebugWin>
<usefulLabel>
3 4 5
</usefulLabel>
<bStandard>1</bStandard>
</iter>
<iter>
<name>smoke</name>
<version>1.6.0</version>
<confidence>0.2</confidence>
<bshowDebugWin>1</bshowDebugWin>
<usefulLabel>
4
</usefulLabel>
<bStandard>1</bStandard>
</iter>
<iter>
<name>motionanalyze</name>
<version></version>
<confidence></confidence>
<bshowDebugWin>1</bshowDebugWin>
<usefulLabel>
</usefulLabel>
</iter>
</Detectors>
<ShowReportWin>1</ShowReportWin>
</SMOKEFireDetection>
</config>
2. 创建XML文件
#include "rapidxml.hpp"
#include "rapidxml_utils.hpp"
#include "rapidxml_print.hpp"
#include <iostream>
#include <string>
#include <fstream>
#include <io.h>
#include <stdlib.h>
void CreateXml(const std::string& XMLFileName)
{
//保存Annotation, 把识别结果写进xml
// DOM
rapidxml::xml_document<> doc;
// node_declaration
//rapidxml::xml_node<>* declaration = doc.allocate_node(rapidxml::node_declaration);
//declaration->append_attribute(doc.allocate_attribute("version", "1.0"));
//declaration->append_attribute(doc.allocate_attribute("encoding", "utf-8"));
//doc.append_node(declaration);
// node_pi
rapidxml::xml_node<>* root = doc.allocate_node(rapidxml::node_pi, doc.allocate_string("xml version='1.0' encoding='utf-8'"));
doc.append_node(root);
// node_comment
rapidxml::xml_node<>* comment = doc.allocate_node(rapidxml::node_comment, 0, " 这是对目标的Annotation保存格式 ");
doc.append_node(comment);
// node_element
rapidxml::xml_node<>* node = doc.allocate_node(rapidxml::node_element, "annotation", "information");
doc.append_node(node);
// node_data
rapidxml::xml_node<>* folder = doc.allocate_node(rapidxml::node_element, "folder", "VOC2007");
node->append_node(folder);
rapidxml::xml_node<>* filename = doc.allocate_node(rapidxml::node_element, "filename", XMLFileName.c_str());
node->append_node(filename);
// node_element with value
rapidxml::xml_node<>* source = doc.allocate_node(rapidxml::node_element, "source", nullptr);
source->append_node(doc.allocate_node(rapidxml::node_element, "database", "My VOC2007 Databas"));
source->append_node(doc.allocate_node(rapidxml::node_element, "annotation", "VOC2007"));
source->append_node(doc.allocate_node(rapidxml::node_element, "image", "flickr"));
source->append_node(doc.allocate_node(rapidxml::node_element, "flickrid", "nullptr"));
node->append_node(source);
rapidxml::xml_node<>* owner = doc.allocate_node(rapidxml::node_element, "owner", nullptr);
owner->append_node(doc.allocate_node(rapidxml::node_element, "flickrid", "nullptr"));
owner->append_node(doc.allocate_node(rapidxml::node_element, "name", "aware"));
node->append_node(owner);
rapidxml::xml_node<>* size = doc.allocate_node(rapidxml::node_element, "size", nullptr);
int width = 1920;
char cw[128];
_itoa_s(width, cw, 128, 10);
size->append_node(doc.allocate_node(rapidxml::node_element, "width", cw));
int height = 1080;
char ch[128];
_itoa_s(height, ch, 128, 10);
size->append_node(doc.allocate_node(rapidxml::node_element, "height", ch));
size->append_node(doc.allocate_node(rapidxml::node_element, "depth", "3"));
node->append_node(size);
rapidxml::xml_node<>* segmented = doc.allocate_node(rapidxml::node_element, "segmented", "0");
node->append_node(segmented);
for (int i = 0; i < 2; i++)
{
// node_comment
rapidxml::xml_node<>* comment = doc.allocate_node(rapidxml::node_comment, 0, " 目标的位置状态信息 ");
node->append_node(comment);
rapidxml::xml_node<>* object = doc.allocate_node(rapidxml::node_element, "object", nullptr);
node->append_node(object);
object->append_node(doc.allocate_node(rapidxml::node_element, "name", doc.allocate_string("example")));
object->append_node(doc.allocate_node(rapidxml::node_element, "pose", "Unspecified"));
object->append_node(doc.allocate_node(rapidxml::node_element, "truncated", "0"));
object->append_node(doc.allocate_node(rapidxml::node_element, "difficult", "0"));
rapidxml::xml_node<>* bndbox = doc.allocate_node(rapidxml::node_element, "bndbox", nullptr);
object->append_node(bndbox);
bndbox->append_node(doc.allocate_node(rapidxml::node_element, "xmin", "11"));
bndbox->append_node(doc.allocate_node(rapidxml::node_element, "ymin", "20"));
bndbox->append_node(doc.allocate_node(rapidxml::node_element, "xmax", "1000"));
bndbox->append_node(doc.allocate_node(rapidxml::node_element, "ymax", "600"));
//打印整个XML内容
std::string text;
rapidxml::print(std::back_inserter(text), doc, 0);
std::cout << text << std::endl;
}
//打印整个XML内容
std::string text;
rapidxml::print(std::back_inserter(text), doc, 0);
std::cout << text << std::endl;
// 输出DOM到文件
std::ofstream outfile(XMLFileName.c_str(), std::ios::out); //ofstream默认时,如果文件存在则覆盖原来的内容,不存在则新建
if (outfile)
{
outfile << doc;
outfile.close();
}
doc.clear();
}
void main()
{
const std::string Xmlfilename = "WriteExample.xml";
CreateXml(Xmlfilename);
std::system("pause");
}
其结果如下图所示:
<?xml version='1.0' encoding='utf-8' ?>
<!--这是对目标的Annotation保存格式-->
<annotation>
<folder>VOC2007</folder>
<filename>WriteExample.xml</filename>
<source>
<database>My VOC2007 Databas</database>
<annotation>VOC2007</annotation>
<image>flickr</image>
<flickrid>nullptr</flickrid>
</source>
<owner>
<flickrid>nullptr</flickrid>
<name>aware</name>
</owner>
<size>
<width>1920</width>
<height>1080</height>
<depth>3</depth>
</size>
<segmented>0</segmented>
<!--目标的位置状态信息 -->
<object>
<name>example</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>11</xmin>
<ymin>20</ymin>
<xmax>1000</xmax>
<ymax>600</ymax>
</bndbox>
</object>
<!--目标的位置状态信息 -->
<object>
<name>example</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>11</xmin>
<ymin>20</ymin>
<xmax>1000</xmax>
<ymax>600</ymax>
</bndbox>
</object>
</annotation>
3. 修改及增加删除
首先是一些对xml的节点解释:
xml_node类
1)node_type type() const; 获取结点类型 获取的类型是枚举的
2)Ch* name() const; 获取结点名
3)std::size_t name_size() const; 获取结点名长度
4)Ch* value() const; 获取结点值
5)std::size_t value_size() const; 获取结点值长度
6)xml_node* first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const; 获取DOM Tree第一个子结点的指针
第一个参数为节点名,如果给定第一个参数为”a”, 则该函数寻找结点名为a的第一个子结点;第二个参数为结点名长度
7)xml_node* last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const; 获取DOM Tree最后一个子结点的指针
参数含义同上
8)xml_attribute* first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const; 获取结点的第一个属性指针
9)xml_attribute* next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const; 获取结点的下一个属性指针
10)xml_attribute* last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const; 获取结点的最后一个属性指针
11)xml_node* previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const; 获取上一个同级结点的指针
12)xml_node* next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const; 获取下一个同级结点的指针
13)xml_attribute* first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const; 获取第一个同级结点的指针
14)xml_attribute* last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const; 获取最后一个同级结点的指针
15)void insert_node(xml_node< Ch > *where, xml_node< Ch > *child); 在第一个参数指向的结点之前,插入一个结点
xml_attribute类
1)xml_attribute *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const; 获取前一个属性
2)xml_attribute *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const;获取后一个属性
#include <iostream>
#include <string>
#include <fstream>
#include "string.h"
#include "rapidxml.hpp"
#include "rapidxml_print.hpp"
#include "rapidxml_utils.hpp"
void modifyXML(const char * file_name)
{
std::string text;
//用file解析DOM时必须是绝对路径
rapidxml::file<> fdoc(file_name);
//打印读取的文件
std::cout<<fdoc.data();
rapidxml::xml_document<> doc;
doc.parse<0>(fdoc.data());
//取得根节点
rapidxml::xml_node<>* root = doc.first_node("config");
//删除第一个元素
if (root->first_node() != nullptr)
root->remove_first_node();
text = "\r\n移除根节点下的第一个元素节点\r\n";
rapidxml::print(std::back_inserter(text), doc, 0); //doc内容输出到text尾处
std::cout << text << std::endl;
rapidxml::xml_node<>* FunctionNode = root->first_node("SMOKEFireDetection");
if (FunctionNode != nullptr)
std::cout << "SMOKEFireDetection is not null" << std::endl;
else
return;
//删除FunctionNode节点的最后一个元素
if (FunctionNode->last_node() != nullptr)
FunctionNode->remove_last_node();
text = "\r\n移除根节点下的FunctionNode的最后一个元素节点\r\n";
rapidxml::print(std::back_inserter(text), doc, 0);
std::cout << text << std::endl;
rapidxml::xml_node<char>* DeteNode = FunctionNode->first_node("Detectors");
if (DeteNode != nullptr)
{
for (rapidxml::xml_node<char>* node = DeteNode->first_node("iter"); node != nullptr; node = node->next_sibling())
{
rapidxml::xml_node<>* pName = node->first_node("name");
if (pName != nullptr && std::string(pName->value()) == "fire")
{
//移除根节点下的FunctionNode结点下第一个循环节点下的bStandardNode节点
rapidxml::xml_node<> *bStandardNode = node->first_node("bStandard");
if (bStandardNode != nullptr)
{
node->remove_node(bStandardNode);
}
//移除根节点下的FunctionNode结点下第一个循环节点下的的usefulLabelNode节点
rapidxml::xml_node<> *usefulLabelNode = node->first_node("usefulLabel");
if (usefulLabelNode != nullptr)
{
node->remove_node(usefulLabelNode);
}
text = "\r\n移除根节点下的FunctionNode结点下第一个循环节点下的bStandardNode节点和usefulLabelNode节点\r\n";
rapidxml::print(std::back_inserter(text), doc, 0);
std::cout << text << std::endl;
continue;
}
else if (pName != nullptr && std::string(pName->value()) == "motionanalyze")
{
//移除根节点下的FunctionNode结点下第三个循环节点下的所有节点
DeteNode->remove_node(node);
break;
}
}
}
text = "\r\n移除根节点下的FunctionNode结点下第三个循环节点下的所有节点\r\n";
rapidxml::print(std::back_inserter(text), doc, 0);
std::cout << text << std::endl;
//在FunctionNode的Detectors节点处插入一个KeyBorad节点
rapidxml::xml_node<>* Graphics = FunctionNode->first_node("Detectors");//找到Graphics节点
rapidxml::xml_node<>* new_node = doc.allocate_node(rapidxml::node_element, "KeyBorad", "Logitech");
new_node->append_attribute(doc.allocate_attribute("Interface", "USB"));
FunctionNode->insert_node(Graphics, new_node);
text = "\r\n在FunctionNode的Detectors节点下面插入一个KeyBorad节点\r\n";
rapidxml::print(std::back_inserter(text), doc, 0);
std::cout << text << std::endl;
写入文件
std::ofstream out("1.xml");
out << doc;
}
int main()
{
const char *file_name = "E:\\VS2015Project\\ReadXmlWriteXml\\ReadXmlWriteXml\\RapidExample.xml";
modifyXML(file_name);
std::system("pause");
return 0;
}
原始数据为:
<config>
<SampleFrequency>25</SampleFrequency>
<SMOKEFireDetection>
<Detectors>
<iter>
<name>fire</name>
<version>1.3.0</version>
<confidence>0.5</confidence>
<bshowDebugWin>1</bshowDebugWin>
<usefulLabel>3 4 5</usefulLabel>
<bStandard>1</bStandard>
</iter>
<iter>
<name>smoke</name>
<version>1.6.0</version>
<confidence>0.2</confidence>
<bshowDebugWin>1</bshowDebugWin>
<usefulLabel>4</usefulLabel>
<bStandard>1</bStandard>
</iter>
<iter>
<name>motionanalyze</name>
<version></version>
<confidence></confidence>
<bshowDebugWin>1</bshowDebugWin>
<usefulLabel>
</usefulLabel>
</iter>
</Detectors>
<ShowReportWin>1</ShowReportWin>
</SMOKEFireDetection>
</config>
修改后为:
<config>
<SMOKEFireDetection>
<KeyBorad Interface="USB">Logitech</KeyBorad>
<Detectors>
<iter>
<name>fire</name>
<version>1.3.0</version>
<confidence>0.5</confidence>
<bshowDebugWin>1</bshowDebugWin>
</iter>
<iter>
<name>smoke</name>
<version>1.6.0</version>
<confidence>0.2</confidence>
<bshowDebugWin>1</bshowDebugWin>
<usefulLabel>4</usefulLabel>
<bStandard>1</bStandard>
</iter>
</Detectors>
</SMOKEFireDetection>
</config>
感谢 https://www.cnblogs.com/MenAngel/p/11552588.html
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/160930.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...