目录
1. github 地址
2. 使用
3. 解析xml demo
4. 注意点
5. 解析效果展示
6.创建xml
7.创建xml效果展示
8. 完整的示例,添加Vector
9. 参考
GitHub - leethomason/tinyxml2: TinyXML2 is a simple, small, efficient, C++ XML parser that can be easily integrated into other programs.
直接把里面的 “tinyxml2.h” 和 “tinyxml2.cpp” 加到自己工程,使用include "tinyxml2.h" 头文件就好
xml内容如下:
UAV_data
NG0_202303032032377079.xml
3070
1600
3
0
代码如下:
#include
#include"tinyxml2.h"
using namespace std;
using namespace tinyxml2;
void decodeXml(std::string xmlPath)
{
//声明
XMLDocument xml;
string value, text;
//导入xml文件
if (xml.LoadFile(xmlPath.c_str()) != XML_SUCCESS)
{
return;
}
//判断头文件是否为空
XMLElement* rootNode = xml.RootElement();
if (rootNode == NULL)
{
return;
}
XMLElement* surface = rootNode->FirstChildElement("object");
while (surface)
{
XMLElement* surfaceChild = surface->FirstChildElement();
while (surfaceChild)
{
// surfaceChild->Value() 是获取节点的名称
value = surfaceChild->Value();
if (value == "bndbox")
{
XMLElement* bndboxChild = surfaceChild->FirstChildElement();
// 因为bndbox节点里面又是节点,所以需要进行循环以及找NextSiblingElement
while (bndboxChild)
{
value = bndboxChild->Value();
text = bndboxChild->GetText();
bndboxChild = bndboxChild->NextSiblingElement();
std::cout << value << ": " << text << std::endl;
}
}
else
{
text = surfaceChild->GetText();
std::cout << value << ": " << text << std::endl;
}
surfaceChild = surfaceChild->NextSiblingElement();
}
surface = surface->NextSiblingElement();
}
}
int main()
{
decodeXml("Z:/temp/cppSaveXml/NG0_202303032032377079.xml");
return 0;
}
1. 整体的逻辑其实就是一层一层的遍历,先找到需要遍历的那个节点,然后通过while和NextSiblingElement来进行循环;
2. surfaceChild->Value() 是获取节点的名称,如果
这个时候就需要用FirstChildElement() 这个方法来获取里面第一个节点的内容,然后再通过while进行循环遍历,如下
if (value == "bndbox")
{
XMLElement* bndboxChild = surfaceChild->FirstChildElement();
// 因为bndbox节点里面又是节点,所以需要进行循环以及找NextSiblingElement
while (bndboxChild)
{
value = bndboxChild->Value();
text = bndboxChild->GetText();
bndboxChild = bndboxChild->NextSiblingElement();
}
}
3. 总的来说,就是一层一层递归,递归的时候需要判断是否是单节点还是里面还包含节点
逻辑就是创建一个根节点,然后再依次创建子节点,然后子节点的 text 属性值设置,然后再把属性值与对应的子节点绑定,然后子节点在与根节点绑定
需要创建如下xml:
NG0_202303032032377079.xml
3070
1600
3
创建代码如下:
XMLElement* getNeedNode(XMLDocument& xml, const char* nodeName, const char* nodeText)
{
XMLElement* node = xml.NewElement(nodeName);
XMLText* node_text = xml.NewText(nodeText);
node->InsertFirstChild(node_text);
return node;
}
void encode()
{
XMLDocument xml;
// 插入声明
XMLDeclaration* declaration = xml.NewDeclaration();
xml.InsertFirstChild(declaration);
// 插入根节点
XMLElement* rootNode = xml.NewElement("annotation");
xml.InsertEndChild(rootNode);
/*------------------新建一个filename节点--------------------------*/
XMLElement* filename = xml.NewElement("filename");
// 设置节点中的值
XMLText* filename_text = xml.NewText("NG0_202303032032377079.xml");
// 把节点中的值与filename节点链接起来
filename->InsertFirstChild(filename_text);
// 将 filename 节点与根节点绑定起来
rootNode->InsertEndChild(filename);
/*------------------新建一个size节点--------------------------*/
XMLElement* size = xml.NewElement("size");
/*------------------新建一个width节点--------------------------*/
XMLElement* width = xml.NewElement("width");
XMLText* width_text = xml.NewText("3070");
width->InsertFirstChild(width_text);
/*------------------新建一个height节点--------------------------*/
XMLElement* height = xml.NewElement("height");
XMLText* height_text = xml.NewText("1600");
height->InsertFirstChild(height_text);
/*------------------新建一个depth节点--------------------------*/
XMLElement* depth = xml.NewElement("depth");
XMLText* depth_text = xml.NewText("3");
depth->InsertFirstChild(depth_text);
// 将 width,height,depth 与 size 节点绑在一起
size->InsertEndChild(width);
size->InsertEndChild(height);
size->InsertEndChild(depth);
/*------------------新建第一个object节点--------------------------*/
XMLElement* object = xml.NewElement("object");
XMLElement* name = xml.NewElement("name");
XMLText* name_text = xml.NewText("round");
name->InsertFirstChild(name_text);
XMLElement* bndbox = xml.NewElement("bndbox");
// getNeedNode 方法为啥是引用,因为是要同一个 XMLDocument 这样才可以绑定, 所以传引用
XMLElement* xmin = getNeedNode(xml, "xmin", "1405");
XMLElement* ymin = getNeedNode(xml, "ymin", "1237");
XMLElement* xmax = getNeedNode(xml, "xmax", "1628");
XMLElement* ymax = getNeedNode(xml, "ymax", "1421");
bndbox->InsertEndChild(xmin);
bndbox->InsertEndChild(ymin);
bndbox->InsertEndChild(xmax);
bndbox->InsertEndChild(ymax);
object->InsertEndChild(name);
object->InsertEndChild(bndbox);
rootNode->InsertEndChild(object);
/*------------------新建第二个object节点--------------------------*/
object = xml.NewElement("object");
name = xml.NewElement("name");
name_text = xml.NewText("long");
name->InsertFirstChild(name_text);
bndbox = xml.NewElement("bndbox");
xmin = getNeedNode(xml, "xmin", "2337");
ymin = getNeedNode(xml, "ymin", "1225");
xmax = getNeedNode(xml, "xmax", "2580");
ymax = getNeedNode(xml, "ymax", "1405");
bndbox->InsertEndChild(xmin);
bndbox->InsertEndChild(ymin);
bndbox->InsertEndChild(xmax);
bndbox->InsertEndChild(ymax);
object->InsertEndChild(name);
object->InsertEndChild(bndbox);
rootNode->InsertEndChild(object);
xml.SaveFile("Z:/temp/cppSaveXml/temp.xml");
}
int main()
{
encode();
return 0;
}
生成xml,使用传入vector,然后循环遍历vector
#include
#include
#include
#include"tinyxml2.h"
//#include "xmlNode.h"
using namespace tinyxml2;
struct Node
{
int imageW;
int imageH;
int channel = 3;
int xmin;
int ymin;
int xmax;
int ymax;
std::string label;
float prob;
Node(int in_w, int in_h, int in_xmin, int in_ymin, int in_xmax, int in_ymax, std::string in_label, float in_prob)
{
imageW = in_w;
imageH = in_h;
xmin = in_xmin;
ymin = in_ymin;;
xmax = in_xmax;;
ymax = in_ymax;;
label = in_label;;
prob = in_prob;;
}
};
void decodeXml(std::string xmlPath)
{
//声明
XMLDocument xml;
std::string value, text;
//导入xml文件
if (xml.LoadFile(xmlPath.c_str()) != XML_SUCCESS)
{
return;
}
//判断头文件是否为空
XMLElement* rootNode = xml.RootElement();
if (rootNode == NULL)
{
return;
}
XMLElement* filename = rootNode->FirstChildElement("filename");
const char* getFileName = filename->GetText();
std::cout << getFileName << std::endl;
XMLElement* surface = rootNode->FirstChildElement("object");
while (surface)
{
XMLElement* surfaceChild = surface->FirstChildElement();
while (surfaceChild)
{
// surfaceChild->Value() 是获取节点的名称
value = surfaceChild->Value();
if (value == "bndbox")
{
XMLElement* bndboxChild = surfaceChild->FirstChildElement();
// 因为bndbox节点里面又是节点,所以需要进行循环以及找NextSiblingElement
while (bndboxChild)
{
value = bndboxChild->Value();
text = bndboxChild->GetText();
bndboxChild = bndboxChild->NextSiblingElement();
std::cout << value << ": " << text << std::endl;
}
}
else
{
text = surfaceChild->GetText();
std::cout << value << ": " << text << std::endl;
}
surfaceChild = surfaceChild->NextSiblingElement();
}
surface = surface->NextSiblingElement();
}
}
XMLElement* getNeedNode(XMLDocument& xml, const char* nodeName, const char* nodeText)
{
XMLElement* node = xml.NewElement(nodeName);
XMLText* node_text = xml.NewText(nodeText);
node->InsertFirstChild(node_text);
return node;
}
void encodeXml(const char* inSaveXmlDir, int inW, int inH, std::vector inAllNode)
{
XMLDocument xml;
// 插入声明
XMLDeclaration* declaration = xml.NewDeclaration();
xml.InsertFirstChild(declaration);
// 插入根节点
XMLElement* rootNode = xml.NewElement("annotation");
xml.InsertEndChild(rootNode);
/*------------------新建一个filename节点--------------------------*/
XMLElement* filename = xml.NewElement("filename");
// 设置节点中的值
XMLText* filename_text = xml.NewText(inSaveXmlDir);
// 把节点中的值与filename节点链接起来
filename->InsertFirstChild(filename_text);
// 将 filename 节点与根节点绑定起来
rootNode->InsertEndChild(filename);
/*------------------新建一个size节点--------------------------*/
XMLElement* size = xml.NewElement("size");
/*------------------新建一个width节点--------------------------*/
XMLElement* width = xml.NewElement("width");
XMLText* width_text = xml.NewText(std::to_string(inW).c_str());
width->InsertFirstChild(width_text);
/*------------------新建一个height节点--------------------------*/
XMLElement* height = xml.NewElement("height");
XMLText* height_text = xml.NewText(std::to_string(inH).c_str());
height->InsertFirstChild(height_text);
/*------------------新建一个depth节点--------------------------*/
XMLElement* depth = xml.NewElement("depth");
XMLText* depth_text = xml.NewText("3");
depth->InsertFirstChild(depth_text);
// 将 width,height,depth 与 size 节点绑在一起
size->InsertEndChild(width);
size->InsertEndChild(height);
size->InsertEndChild(depth);
rootNode->InsertEndChild(filename);
rootNode->InsertEndChild(size);
/*------------------新建第一个object节点--------------------------*/
for (auto node : inAllNode)
{
XMLElement* object = xml.NewElement("object");
XMLElement* name = xml.NewElement("name");
XMLText* name_text = xml.NewText(node.label.c_str());
name->InsertFirstChild(name_text);
XMLElement* bndbox = xml.NewElement("bndbox");
// getNeedNode 方法为啥是引用,因为是要同一个 XMLDocument 这样才可以绑定, 所以传引用
XMLElement* xmin = getNeedNode(xml, "xmin", std::to_string(node.xmin).c_str());
XMLElement* ymin = getNeedNode(xml, "ymin", std::to_string(node.ymin).c_str());
XMLElement* xmax = getNeedNode(xml, "xmax", std::to_string(node.xmax).c_str());
XMLElement* ymax = getNeedNode(xml, "ymax", std::to_string(node.ymax).c_str());
bndbox->InsertEndChild(xmin);
bndbox->InsertEndChild(ymin);
bndbox->InsertEndChild(xmax);
bndbox->InsertEndChild(ymax);
object->InsertEndChild(name);
object->InsertEndChild(bndbox);
rootNode->InsertEndChild(object);
}
xml.SaveFile(inSaveXmlDir);
}
int main()
{
const char* saveXmlDir = "Z:/temp/cppSaveXml/1.xml";
std::vector allNode;
Node nodeOne = { 1, 2, 3, 4, 5, 6, "1", 0.1 };
Node nodeTwo = { 1, 2, 3, 4, 5, 6, "2", 0.1 };
allNode.push_back(nodeOne);
allNode.push_back(nodeTwo);
encodeXml(saveXmlDir, 3070, 1600, allNode);
return 0;
}
效果展示
1. C++解析XML文件_c++ xml解析_时·风·人的博客-CSDN博客