C++ 使用 tinyxml2 解析创建 xml

article/2025/9/26 5:52:24

目录

1. github 地址

2. 使用

3. 解析xml demo

4. 注意点

5. 解析效果展示

6.创建xml

7.创建xml效果展示

8. 完整的示例,添加Vector

9. 参考


1. github 地址

GitHub - leethomason/tinyxml2: TinyXML2 is a simple, small, efficient, C++ XML parser that can be easily integrated into other programs.

2. 使用

直接把里面的 “tinyxml2.h” 和 “tinyxml2.cpp” 加到自己工程,使用include "tinyxml2.h" 头文件就好

3. 解析xml demo

xml内容如下:

<?xml version="1.0" encoding="utf-8"?>
<annotation><folder>UAV_data</folder><filename>NG0_202303032032377079.xml</filename><size><width>3070</width><height>1600</height><depth>3</depth></size><segmented>0</segmented><object><name>round</name><location>0</location><diffcult>0</diffcult><diffcultt>3</diffcultt><bndbox><xmin>1405</xmin><ymin>1237</ymin><xmax>1628</xmax><ymax>1421</ymax></bndbox></object><object><name>long</name><diffcult>0</diffcult><location>0</location><bndbox><xmin>2337</xmin><ymin>1225</ymin><xmax>2580</xmax><ymax>1405</ymax></bndbox></object>
</annotation>

代码如下:

#include <iostream>  
#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节点里面又是节点,所以需要进行循环以及找NextSiblingElementwhile (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;
}

4. 注意点

1. 整体的逻辑其实就是一层一层的遍历,先找到需要遍历的那个节点,然后通过while和NextSiblingElement来进行循环;

2. surfaceChild->Value() 是获取节点的名称,如果 <name>round</name> 得到的是name。这里需要注意的就是,如果节点里面又有节点,这个时候就不能用 surfaceChild->GetText() 来获取里面的值,因为里面是节点,不是单纯的值,如果仍然使用GetText()会报错。
这个时候就需要用FirstChildElement() 这个方法来获取里面第一个节点的内容,然后再通过while进行循环遍历,如下

if (value == "bndbox")
{XMLElement* bndboxChild = surfaceChild->FirstChildElement();// 因为bndbox节点里面又是节点,所以需要进行循环以及找NextSiblingElementwhile (bndboxChild){value = bndboxChild->Value();text = bndboxChild->GetText();bndboxChild = bndboxChild->NextSiblingElement();}
}

3. 总的来说,就是一层一层递归,递归的时候需要判断是否是单节点还是里面还包含节点

5. 解析效果展示

6.创建xml

逻辑就是创建一个根节点,然后再依次创建子节点,然后子节点的 text 属性值设置,然后再把属性值与对应的子节点绑定,然后子节点在与根节点绑定

需要创建如下xml:

<?xml version="1.0" encoding="utf-8"?>
<annotation><filename>NG0_202303032032377079.xml</filename><size><width>3070</width><height>1600</height><depth>3</depth></size><object><name>round</name><bndbox><xmin>1405</xmin><ymin>1237</ymin><xmax>1628</xmax><ymax>1421</ymax></bndbox></object><object><name>long</name><bndbox><xmin>2337</xmin><ymin>1225</ymin><xmax>2580</xmax><ymax>1405</ymax></bndbox></object>
</annotation>

创建代码如下:

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;
}

7.创建xml效果展示

8. 完整的示例,添加Vector

生成xml,使用传入vector,然后循环遍历vector

#include <iostream>  
#include <vector>
#include <string>
#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节点里面又是节点,所以需要进行循环以及找NextSiblingElementwhile (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<Node> 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<Node> 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;
}

效果展示

9. 参考

1. C++解析XML文件_c++ xml解析_时·风·人的博客-CSDN博客


http://chatgpt.dhexx.cn/article/yklGpZ1N.shtml

相关文章

TinyXML2 学习

换cocos2d-x版本到2.1.3之后&#xff0c;自己的文件读写也用了引擎CCUserDefault使用的TinyXML2&#xff0c;在这汇总了一下TinyXML2的使用&#xff0c;希望大家看这一篇文章就可以解决自己的问题&#xff0c;省得到处查阅…… 注意&#xff0c;文章一次解释了写操作->读操…

Tiny-XML

Tiny-XML 2023-01-15:基于C语言实现的小型XML解析器 解析代码实现仅600余行大部分数据结构使用链表实现&#xff0c;malloc、free、realloc、strdup函数已在文件开头使用宏定义设置&#xff0c;方便移植于别的平台项目注释内容丰富&#xff0c;数据结构和常用函数方法已于文件…

xml开发笔记(一):tinyXml2库介绍、编译和工程模板

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://blog.csdn.net/qq21497936/article/details/111828450 长期持续带来更多项目与技术分享&#xff0c;咨询请加QQ:21497936、微信&#xff1a;yangsir198808 红胖子(红模仿)的博文大全&#x…

tinyxml2的安装使用及示例总结

TinyXml2 库使用方法 安装 下载地址 https://github.com/leethomason/tinyxml2 使用 git 下载 &#xff08;1&#xff09;下载 tinyxml2 git clone https://github.com/leethomason/tinyxml2.git &#xff08;2&#xff09;进入相应目录并编译 cd tinyxml2/ cmake . make &…

C++使用TinyXml2解析Xml

1. TinyXml2 简介 TinyXml 一直是一个非常好用的 Xml 解析工具 , 最新的开源版本 TinyXml2 相对于旧版本的 TinyXml 使用更少的内存 , 更快 , 并且使用更少的内存分配 , 现在是所有开发的重点 , 经过良好的测试 , 是您的最佳选择 , 除非您有维护TinyXML-1代码的要求 ; TinyX…

使用tinyxml2库解析xml

tinyxml2简介 tinyxml2是c编写的轻量级的xml解析器&#xff0c;而且是开放源代码的&#xff0c;在一些开源的游戏引擎中用的比较多。源码托管在github上。 源码地址&#xff1a;https://github.com/leethomason/tinyxml2 tinyxml2使用起来非常简单&#xff0c;下载源码后无需…

TinyXml学习笔记

TinyXml学习笔记 张弛<> 注:本文的最新版本可以在下面的地址找到 http://amidiot.512j.com/article/tinyxml/tinyxml_note.htm 一、 TinyXml的特点 TinyXml是一个基于DOM模型的、非验证的轻量级C解释器。 1. SAX和DOM 目前XML的解析主要有两大模型&#…

TinyXml使用详解

本文用一个详细的例子说明了TinyXml的使用方法。如写、查找、插入、替换、加载、遍历等常见操作。 首先简单介绍一下TinyXml,要看详细的在网上搜搜了^_^: 1、TinyXml源代码只有4个cpp文件和2个头文件。 2、首先要理解TinyXml中的各个基本类型之间的关系,看看这个继承图大家…

TinyXML2使用教程

TinyXML2使用教程 原文转自 http://blog.csdn.net/K346K346/article/details/48750417 1.TinyXML2概述 TinyXML2是simple、small、efficient开源的C XML文件解析库&#xff0c;可以很方便的应用到现有的项目之中。非常适合存储简单数据&#xff0c;配置文件&#xff0c;对象…

TinyXML使用方法

TinyXML 使用说明 TinyXML是一个C的XML解析库&#xff0c;网上的评价都不错&#xff0c;是一个轻量级的XML解析库。关于TinyXML使用的文章有很多&#xff0c;而且官方也有完整的文档&#xff0c;这里只是简单把自己使用记录写下来&#xff0c;方便以后查阅。 一个XML文档例子&…

C++ 本地使用tinyxml2解析Xml文件

1、基本介绍 TinyXML2是一个开源、简单、小巧、高效的C XML解析器&#xff0c;它只有一个.h文件和一个.cpp文件组成&#xff0c;可以轻松集成到其它程序中。非常方便我们使用c对xml进行处理。 可以读取、修改和保存的文档对象模型(Document Object Model, DOM)。它不能解析DTD…

快速上手 TinyXML-2 不完全教程

TinyXML-2 不完全教程 XML 作为程序开发中非常常用的数据文档之一&#xff0c;各个语言或是开发环境都有对应的用于处理 XML 文件的库。在 C 语言中&#xff0c;TinyXML-2 就是这样的一个库。 TinyXML-2 是一个简单&#xff0c;小巧&#xff0c;高性能的 C 的 XML 解析器&…

开源库TinyXML2简介及使用

TinyXML2是一个开源、简单、小巧、高效的C XML解析器&#xff0c;它只有一个.h文件和一个.cpp文件组成&#xff0c;可以轻松集成到其它程序中。它解析XML文档并从中构建可以读取、修改和保存的文档对象模型(Document Object Model, DOM)。它不能解析DTD(Document Type Definiti…

c/c++操作xml库-Tinyxml2入门及高级用法

一、概念 TinyXML2是一个开源、简单、小巧、高效的C XML解析器&#xff0c;它只有一个.h文件和一个.cpp文件组成&#xff0c;可以轻松集成到其它程序中。它解析XML文档并从中构建可以读取、修改和保存的文档对象模型(Document Object Model, DOM)。它不能解析DTD(Document Typ…

关于Anaconda卸载干净的问题【已解决】

在卸载anaconda时&#xff0c;为了卸载干净&#xff0c;一般会在win10自带的 应用与功能中选择anaconda 进行卸载。 &#xff0c;也可以用anaconda文件中卸载程序Uninstall-Anaconda3.exe进行卸载。 然后再把相应路径下的剩余文件删掉。 但是&#xff01; 这还不够&#xff0c…

anaconda卸载后重装问题

记录一下anaconda卸载后&#xff0c;重新安装后缺少很多文件&#xff0c;重装后打开Anaconda Navigator&#xff0c;发现内容一片空白&#xff0c;软件也不见了&#xff0c;库也不见了&#xff0c;开始菜单也没有anaconda和anaconda prompt&#xff0c;只有如下很少的文件。网上…

如何彻底卸载Anaconda3

阅览了其他大神的卸载文章后&#xff0c;如 https://blog.csdn.net/qq_40605139/article/details/95249601 这篇就给了我很多指导&#xff0c;但我在运行第一句的 conda install anaconda-clean 后就出错了&#xff0c;提示截图如下&#xff1a; 然后就是各种百度&#xff0c;…

Anaconda卸载后重装过程

文章目录 前言一、卸载二、删除注册表三、下载安装包四、安装五、改环境变量六、检验参考文章 前言 因为之前装虚拟机的时候清理磁盘被迫卸掉anaconda&#xff0c;现在又要用jupyter notebook写作业&#xff0c;所以重新装了一遍&#xff0c;记录一下过程备用&#xff0c;也是…

anaconda卸载后重装的悲剧

在经历了无比绝望的一天后&#xff0c;我终于在意志消磨完的最后一刻成功完成了anaconda的卸载重装&#xff0c;这一天过的可以说是非常绝望了。上午还在开开心心的准备下载pytorch库进行学习&#xff0c;结果在更新依赖库的时候没有使用虚拟环境结果导致anaconda崩了&#xff…

CentOS安装/卸载Anaconda(图文详解)

目录 一、Anaconda下载 二、安装Anaconda 三、添加环境 四、卸载 1.删除anaconda文件目录 2.清理.bashrc中的Anaconda路径 一、Anaconda下载 众所周知的原因&#xff0c;从官网下载Anaconda非常慢&#xff0c;因此为了加速下载&#xff0c;这里我们采取清华源下载。 不…