tinyxml2的入门教程
- 前言
- 一、tinyxml2 创建xml 文件
- 二、tinyxml2 添加数据
- 三、tinyxml2 更改数据
- 四、tinyxml2 删除数据
- 五、tinyxml2 打印
- 总结
前言
xml 是一种标记型文档,有两种基本解析方式:DOM(Document Object Model,文档对象模型)和SAX(Simple APIs for XML,简单应用程序接口)。

DOM 将 xml 文档全部内容解析成一个对象模型树,通过对这个对象模型进行操作来实现对数据的操作。
-  优点: 
 – 解析成树的结构对象,可以实现增删改操作
-  缺点: 
 – 当 xml 文件过大时,比较占用内存
SAX 以事务为驱动,对 xml 文档从上之下,一行一行解析,当解析到事务对象则返回。
-  优点: 
 – 一行一行解析,内存占用小
-  缺点: 
 – 无能进行增删改操作
目前,有很多库封装了对 xml 文档的操作,例如 mini-xml 、libxml2、Xerces和 tinyxml等。tinyxml2 是其中一个比较简单且高效的 C ++ xml 解析器,只有一个.h 的头文件和一个 . pp 的源文件,可以轻松集成进自己的程序中。
tinyxml2采用DOM解析方式,
在 tinyxml2 中,节点是解析的基本单元,包括 文档节点(XMLDocument)、元素节点(XMLElement)、属性节点(XMLAttribute)和文本节点(XMLText)。对于 xml 文档中数据的增删改查都是基于这些节点进行操作的。
一、tinyxml2 创建xml 文件
首先,最好把 tinyxml2 的头文件和源文件放项目下:

 然后就是引入 tinyxml2 的头文件并链接源文件。这里,用的是 cmake 来构建,将 tinyxml2 文件夹的路径包含进来,然后将源文件链接到 可执行文件上就行。

 最后,假设现在创建一个关于 地图的 xml 数据文件
#include <iostream>
#include "tinyxml2/tinyxml2.h"
using namespace std;
using namespace tinyxml2;
struct point {
    double x;
    double y;
    point(double x, double y) : x(x), y(y) {};
};
// 创建一个XML文件
int createXML(const char *xmlPath) {
    // 定义文档节点
    XMLDocument xmlDoc;
    // 如果文件存在,则返回-1
    if (xmlDoc.LoadFile(xmlPath) != XML_ERROR_FILE_NOT_FOUND) {
        cout << "The xml file is exits" << endl;
        return -1;
    }
    // 创建根节点 <MAP>
    XMLElement *root = xmlDoc.NewElement("MAP");
    xmlDoc.InsertFirstChild(root);
    // 创建根节点下的 header 元素节点
    XMLElement *header = xmlDoc.NewElement("header");
    root->InsertFirstChild(header);
    // 设置 header 元素节点的属性
    header->SetAttribute("type", "");
    header->SetAttribute("name", "两驱MRL1300-无反识别");
    // 创建并设置 header 节点下的 min_pos 和 max_pos 元素节点
    XMLElement *min_pos = xmlDoc.NewElement("min_pos");
    min_pos->SetAttribute("x", "-46.00000");
    min_pos->SetAttribute("y", "-57.000000");
    header->InsertFirstChild(min_pos);
    XMLElement *max_pos = xmlDoc.NewElement("max_pos");
    max_pos->SetAttribute("x", "91.00000");
    max_pos->SetAttribute("y", "43.000000");
    header->InsertFirstChild(max_pos);
    // 在根节点下 加个注释
    root->InsertNewComment("This is a comment");
    // 在根节点下 加入 footer 元素节点,并设置文本内容
    XMLElement *footer = xmlDoc.NewElement("footer");
    footer->InsertNewText("This is a footer");
    root->InsertEndChild(footer);
    // 保存 xml 文件
    return xmlDoc.SaveFile(xmlPath);
}
int main(int argc, char *argv[]) {
    srand(unsigned(time(NULL)));
    const char *filename = "MAP.xml";
    if(createXML(filename) != XML_SUCCESS)
    {
        cout<<"Create xml file failed"<<endl;
        return 0;
    }
}
没指定决定路径的话,可以在编译文件夹中看到已经创建了一个 MAP.xml 文件

二、tinyxml2 添加数据
现在,为刚创建的 MAP.xml 文件,添加一些点云坐标
int addXML(const char *XMLPath) {
    // 文档节点 xmlDoc
    XMLDocument xmlDoc;
    if (xmlDoc.LoadFile(XMLPath) != XML_SUCCESS) {
        cout << "The xml file is not exits" << endl;
        return -1;
    }
    // 获取文档节点的 根节点 root
    XMLElement *root = xmlDoc.RootElement();
    // 添加一些随机坐标点
    for (int i = 0; i < 100; i++) {
        point p(rand() * 0.001, rand() * 0.002);
        // 定义坐标元素节点 point
        XMLElement *point = xmlDoc.NewElement("point");
        // 设置元素节点 point 的属性和值
        point->SetAttribute("x", p.x);
        point->SetAttribute("y", p.y);
        // 将元素节点 point 添加到根节点 root下
        root->InsertEndChild(point);
    }
    // 保存 xml 文件
    return xmlDoc.SaveFile(XMLPath);
}
可以看到,已经在root节点中加入了 坐标元素了

三、tinyxml2 更改数据
更改操作里面就用到了 查询 操作(判断):将 x 属性值为0 的所有点元素的 y 属性值都改为2,在改之前,先添加一些x为0的点元素,在addXML()中加入:
// 添加一些指定点
    for (int i = 0; i < 100; i++) {
        point p(0,  1);
        // 定义坐标元素节点 point
        XMLElement *point = xmlDoc.NewElement("point");
        // 设置元素节点 point 的属性和值
        point->SetAttribute("x", p.x);
        point->SetAttribute("y", p.y);
        // 将元素节点 point 添加到根节点 root下
        root->InsertEndChild(point);
    }
在随机坐标点下就有了指定坐标点了

然后再进行查询并修改这些点
int modifyXML(const char *XMLPath) {
    // 文档节点
    XMLDocument xmlDoc;
    if (xmlDoc.LoadFile(XMLPath) != XML_SUCCESS) {
        cout << "The xml file is not exits" << endl;
        return -1;
    }
    // 获取 文档节点中的 root 根节点
    XMLElement *root = xmlDoc.RootElement();
    // 定义要修改的元素节点
    XMLElement *point = root->FirstChildElement("point");
    // 将所有 x 属性为 0 的 point 的 y 属性值都改为 2
    while (point != nullptr) {
        const char *x = point->Attribute("x");
        if (x && strcmp(x, "0") == 0) {
            point->SetAttribute("y", 2);
            cout << "modify done" << endl;
        }
        point = point->NextSiblingElement("point");
    }
    // 保存
    return xmlDoc.SaveFile(XMLPath);
}
这样,就将 x 属性值为 0 点的 y 属性值改为2了

四、tinyxml2 删除数据
这里,删除 x 属性值为 0 的 point 元素。
int deleteXML(const char *XMLPath) {
    // 文档节点
    XMLDocument xmlDoc;
    if (xmlDoc.LoadFile(XMLPath) != XML_SUCCESS) {
        cout << "The xml file is not exits" << endl;
        return -1;
    }
    // 获取 根节点 root
    XMLElement *root = xmlDoc.RootElement();
    // 准备要被删除的元素
    XMLElement *point = root->FirstChildElement("point");
    while (point != nullptr) {
        const char *x = point->Attribute("x");
        // 删除 x 属性值 为 0 的 point 元素
        if (x && strcmp(x, "0") != 0) {
            point = point->NextSiblingElement("point");
        } else {
            XMLElement *delete_point = point;
            point = point->NextSiblingElement("point");
            root->DeleteChild(delete_point);
            cout << "delete done" << endl;
        }
    }
    // 保存
    return xmlDoc.SaveFile(XMLPath);
}
这样, x 属性值为 0 的 point 元素就被全部删除了

五、tinyxml2 打印
void printXML(const char *XMLPath) {
    // 文档节点
    XMLDocument xmlDoc;
    if (xmlDoc.LoadFile(XMLPath) != XML_SUCCESS) {
        cout << "The xml file is not exits" << endl;
        return;
    }
    XMLPrinter printer;
    xmlDoc.Print(&printer);
    cout << printer.CStr() << endl;
}

总结
tinyxml2 解析 xml 文件的过程操作还是比较简单易上手的。最后,完整代码如下:
#include <iostream>
#include "tinyxml2/tinyxml2.h"
using namespace std;
using namespace tinyxml2;
struct point {
    double x;
    double y;
    point(double x, double y) : x(x), y(y) {};
};
// 创建一个XML文件
int createXML(const char *xmlPath) {
    // 定义文档节点
    XMLDocument xmlDoc;
    // 如果文件存在,则返回-1
    if (xmlDoc.LoadFile(xmlPath) != XML_ERROR_FILE_NOT_FOUND) {
        cout << "The xml file is exits" << endl;
        return -1;
    }
    // 创建根节点 <MAP>
    XMLElement *root = xmlDoc.NewElement("MAP");
    xmlDoc.InsertFirstChild(root);
    // 创建根节点下的 header 元素节点
    XMLElement *header = xmlDoc.NewElement("header");
    root->InsertFirstChild(header);
    // 设置 header 元素节点的属性
    header->SetAttribute("type", "");
    header->SetAttribute("name", "激光点云地图");
    // 创建并设置 header 节点下的 min_pos 和 max_pos 元素节点
    XMLElement *min_pos = xmlDoc.NewElement("min_pos");
    min_pos->SetAttribute("x", "-46.00000");
    min_pos->SetAttribute("y", "-57.000000");
    header->InsertFirstChild(min_pos);
    XMLElement *max_pos = xmlDoc.NewElement("max_pos");
    max_pos->SetAttribute("x", "91.00000");
    max_pos->SetAttribute("y", "43.000000");
    header->InsertFirstChild(max_pos);
    // 在根节点下 加个注释
    root->InsertNewComment("This is a comment");
    // 在根节点下 加入 footer 元素节点,并设置文本内容
    XMLElement *footer = xmlDoc.NewElement("footer");
    footer->InsertNewText("This is a footer");
    root->InsertEndChild(footer);
    // 保存 xml 文件
    return xmlDoc.SaveFile(xmlPath);
}
int addXML(const char *XMLPath) {
    // 文档节点 xmlDoc
    XMLDocument xmlDoc;
    if (xmlDoc.LoadFile(XMLPath) != XML_SUCCESS) {
        cout << "The xml file is not exits" << endl;
        return -1;
    }
    // 获取文档节点的 根节点 root
    XMLElement *root = xmlDoc.RootElement();
    // 添加一些指定点
    for (int i = 0; i < 100; i++) {
        point p(0,  1);
        // 定义坐标元素节点 point
        XMLElement *point = xmlDoc.NewElement("point");
        // 设置元素节点 point 的属性和值
        point->SetAttribute("x", p.x);
        point->SetAttribute("y", p.y);
        // 将元素节点 point 添加到根节点 root下
        root->InsertEndChild(point);
    }
    // 添加一些随机坐标点
    for (int i = 0; i < 100; i++) {
        point p(rand() * 0.001, rand() * 0.002);
        // 定义坐标元素节点 point
        XMLElement *point = xmlDoc.NewElement("point");
        // 设置元素节点 point 的属性和值
        point->SetAttribute("x", p.x);
        point->SetAttribute("y", p.y);
        // 将元素节点 point 添加到根节点 root下
        root->InsertEndChild(point);
    }
    // 保存 xml 文件
    return xmlDoc.SaveFile(XMLPath);
}
int modifyXML(const char *XMLPath) {
    // 文档节点
    XMLDocument xmlDoc;
    if (xmlDoc.LoadFile(XMLPath) != XML_SUCCESS) {
        cout << "The xml file is not exits" << endl;
        return -1;
    }
    // 获取 文档节点中的 root 根节点
    XMLElement *root = xmlDoc.RootElement();
    // 定义要修改的元素节点
    XMLElement *point = root->FirstChildElement("point");
    // 将所有 x 属性为 0 的 point 的 y 属性值都改为 2
    while (point != nullptr) {
        const char *x = point->Attribute("x");
        if (x && strcmp(x, "0") == 0) {
            point->SetAttribute("y", 2);
            cout << "modify done" << endl;
        }
        point = point->NextSiblingElement("point");
    }
    // 保存
    return xmlDoc.SaveFile(XMLPath);
}
int deleteXML(const char *XMLPath) {
    // 文档节点
    XMLDocument xmlDoc;
    if (xmlDoc.LoadFile(XMLPath) != XML_SUCCESS) {
        cout << "The xml file is not exits" << endl;
        return -1;
    }
    // 获取 根节点 root
    XMLElement *root = xmlDoc.RootElement();
    // 准备要被删除的元素
    XMLElement *point = root->FirstChildElement("point");
    while (point != nullptr) {
        const char *x = point->Attribute("x");
        // 删除 x 属性值 为 0 的 point 元素
        if (x && strcmp(x, "0") != 0) {
            point = point->NextSiblingElement("point");
        } else {
            XMLElement *delete_point = point;
            point = point->NextSiblingElement("point");
            root->DeleteChild(delete_point);
            cout << "delete done" << endl;
        }
    }
    // 保存
    return xmlDoc.SaveFile(XMLPath);
}
void printXML(const char *XMLPath) {
    // 文档节点
    XMLDocument xmlDoc;
    if (xmlDoc.LoadFile(XMLPath) != XML_SUCCESS) {
        cout << "The xml file is not exits" << endl;
        return;
    }
    XMLPrinter printer;
    xmlDoc.Print(&printer);
    cout << printer.CStr() << endl;
}
int main(int argc, char *argv[]) {
    srand(unsigned(time(NULL)));
    const char *filename = "MAP.xml";
    if(createXML(filename) != XML_SUCCESS)
    {
        cout<<"Create xml file failed"<<endl;
        return 0;
    }
    if (addXML(filename) != XML_SUCCESS) {
        cout << "Add xml file failed" << endl;
        return 0;
    }
    if (modifyXML(filename) != XML_SUCCESS) {
        cout << "Modify xml file failed" << endl;
        return 0;
    }
    if (deleteXML(filename) != XML_SUCCESS) {
        cout << "Delete xml file failed" << endl;
        return 0;
    }
    printXML(filename);
}


![[Meachines] Lame smbd3.0-RCE](https://img-blog.csdnimg.cn/img_convert/cd3694ded6596ad14db63623e4f2568f.jpeg)















