tinyxml2的入门教程

tinyxml2的入门教程

  • 前言
  • [一、tinyxml2 创建xml 文件](#一、tinyxml2 创建xml 文件)
  • [二、tinyxml2 添加数据](#二、tinyxml2 添加数据)
  • [三、tinyxml2 更改数据](#三、tinyxml2 更改数据)
  • [四、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 数据文件

cpp 复制代码
#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 文件,添加一些点云坐标

cpp 复制代码
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()中加入:

cpp 复制代码
// 添加一些指定点
    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);
    }

在随机坐标点下就有了指定坐标点了

然后再进行查询并修改这些点

cpp 复制代码
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 元素。

cpp 复制代码
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 打印

cpp 复制代码
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 文件的过程操作还是比较简单易上手的。最后,完整代码如下:

cpp 复制代码
#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);

}
相关推荐
武子康2 天前
Java-39 深入浅出 Spring - AOP切面增强 核心概念 通知类型 XML+注解方式 附代码
xml·java·大数据·开发语言·后端·spring
Ll13045252983 天前
基于 COM 的 XML 解析技术(MSXML) 的总结
xml
在代码的海洋中寻找亚特兰蒂斯4 天前
AJAX对于XML和JSON的处理
xml·ajax·json
BinField5 天前
ToolsSet之:XML工具
xml·windows·microsoft
SEO-狼术5 天前
Connect Directly to Oracle XML Data
xml·数据库·oracle
YSoup6 天前
2025年目前最新版本Android Studio自定义xml预览的屏幕分辨率
android·xml·android studio
abcnull7 天前
mybatis的mapper对应的xml写法
xml·sql·spring·mybatis·mapper
Blue桃之夭夭7 天前
HTML、XML、JSON 是什么?有什么区别?又是做什么的?
xml·html·json
小于村7 天前
pom.xml 文件中配置你项目中的外部 jar 包打包方式
xml·java·jar
扶风呀7 天前
pom.xml中标签详解_
xml