QT调用Tinyxml2库解析XML结构文件

在学习SVG结构的时候,发现SVG结构可以通过以XML文件直接解析,所以就去了解了Tinyxml2库 的使用,相关教程也比较多。

个人感觉Tinyxml2库 比官方的XML解析库更好用,这里做个技术总结,记录Tinyxml2库解析XML文件结构的简单使用。

目录导读

    • [Tinyxml2库 介绍(文言一心)](#Tinyxml2库 介绍(文言一心))
    • [使用CMAKE 和 MSVC 2017 编译 Tinyxml2库](#使用CMAKE 和 MSVC 2017 编译 Tinyxml2库)
    • [QT 调用 **tinyxml2.lib** 解析XML](#QT 调用 tinyxml2.lib 解析XML)

Tinyxml2库 介绍(文言一心)

TinyXML-2 是一个简单、小巧且功能强大的C++ XML解析库,它是TinyXML的改进和扩展版本。该库专注于易用性和性能,提供了对XML文档的读取、修改和创建功能。以下是TinyXML-2的主要特点:

  • DOM风格API: TinyXML-2采用了Document Object Model(DOM)风格的API,允许开发者以树形结构的方式操作XML数据。这意味着开发者可以轻松地遍历、查询和修改XML文档。
  • 轻量级: TinyXML-2的代码量小,不依赖外部库,因此非常适合嵌入式系统和移动设备。由于其小巧的体积和高效的实现,它在处理XML文档的速度上表现出色。
  • 易于使用: TinyXML-2的API设计直观、简洁,类和方法命名直观(如XMLNode、XMLElement等),使得学习成本较低,易于理解和集成到项目中。
  • 错误处理: TinyXML-2提供了一套全面的错误检查机制。如果遇到无效的XML格式,它会抛出异常或返回错误代码,帮助开发者快速定位问题。
    支持解析和生成:TinyXML-2支持从字符串或文件中解析XML文档,并且可以生成格式良好的XML文本。它能够处理各种节点类型,如元素、属性、文本、注释等。
  • 跨平台: TinyXML-2完全基于标准C++编写,可以在多种操作系统和编译器环境下运行,包括Windows、Linux、Mac OS X等。

总的来说,TinyXML-2是一个功能强大、易于使用且跨平台的C++ XML解析库,适用于各种需要处理XML数据的场景。

Github: https://github.com/leethomason/tinyxml2

使用CMAKE 和 MSVC 2017 编译 Tinyxml2库

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

下载最新GitHub的项目通过CMAKE编译:
Configure 选择MSCV2017编译器和X64平台:

直接ConfigureGenerate 生成VS2017项目,可能是编译器或版本文件没有出现任何异常...

项目工程直接生成 tinyxml2.lib 没有了dll文件。
xmltest.cpp 文件为调用示例,建议参考。

QT 调用 tinyxml2.lib 解析XML

将项目中的 tinyxml2.htinyxml2.cpptinyxml2.lib 放在项目目录下。

cpp 复制代码
#include "tinyxml2/tinyxml2.h"

using namespace tinyxml2;
using namespace std;

//! tinyxml2.lib 绝对路径
#pragma comment(lib,"E:\\data-bank\\Git\\Qt_XML_Lanalysis\\Qt_XML_Lanalysis\\XML_LAnalysis_UI\\tinyxml2\\tinyxml2.lib")

遍历所有节点

加载XML文件遍历所有节点,并输出节点中的所有属性值

参考:tinyxml/tinyxml2遍历所有节点

cpp 复制代码
#include <QDebug>
#include <QObject>
#include <QFileInfo>

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <wchar.h>


void Lib_XmlReadWrite::GetEleValue(XMLElement * element)
{
    for (XMLElement* currentele = element->FirstChildElement(); currentele; currentele = currentele->NextSiblingElement())
    {
        XMLElement* tmpele = currentele;
        if (currentele->Name() != NULL||currentele->GetText() != NULL)
            qDebug() <<"-->" << currentele->Name() << ":" << currentele->GetText() ;
		
        if(tmpele->FirstAttribute()!=NULL)
        {
            //! 输出所有属性值
            for (const XMLAttribute* var =tmpele->FirstAttribute(); var;var=var->Next()) {
                qDebug()<<"---->" <<var->Name()<<" : "<<var->Value();
            }
        }
		
		//! 有子节点继续加载
        if (!tmpele->NoChildren())
            GetEleValue(tmpele);
    }
}


void Lib_XmlReadWrite::LoadXML(QString xml)
{
    QFileInfo info("C:\\Users\\admin\\Desktop\\textxml\\text_xml5.xml");

    qDebug()<< "LoadXML -->"<<info.exists();
    XMLDocument doc;
    doc.LoadFile(info.absoluteFilePath().toStdString().c_str());
    qDebug()<<doc.ErrorIDToName(doc.ErrorID());

    qDebug()<< doc.FirstChild()->FirstChildElement()->Name();
    qDebug()<<doc.RootElement()->Name();
    qDebug()<<"-----------------------------------";
    GetEleValue(doc.RootElement());


}

将XML节点 加载到QTreeWidget 控件上

通过 QTreeWidgetItem 结构将XML相关结构显示到 QTreeWidget 控件上。

值得注意的是 如果一个文件有多个根节点可以通过
for (XMLElement* root = doc.RootElement(); root; root = root->NextSiblingElement())

遍历所有根节点。

cpp 复制代码
bool Lib_XmlReadWrite::LoadTreeWidget(QString xmlpath,QTreeWidgetItem* & item,QString& ErrorStr)
{
    //! 判断文件是否存在!
   QFileInfo xmlInfo(xmlpath);
    if(!xmlInfo.exists())
    {
        ErrorStr=("文件["+QString(xmlpath)+"]不存在!");
        return false;
    }

    //! 加载xml格式文件
    doc.Clear();;
    doc.LoadFile(xmlInfo.absoluteFilePath().toStdString().c_str());

    if(doc.ErrorID()!=XML_SUCCESS)
    {
        ErrorStr=("解析失败:"+QString(doc.ErrorStr()));
        return false;
    }

    //! 添加文件根目录
    item=new QTreeWidgetItem(QStringList()<<QString(xmlInfo.baseName())<<""<<xmlInfo.absoluteFilePath());
    //! 不一定只有一个节点
    for (XMLElement* root = doc.RootElement(); root; root = root->NextSiblingElement())
    {
        //! XML子节点
        QTreeWidgetItem* rootitem=new QTreeWidgetItem(QStringList()<<QString(root->Name())<<""<<root->GetText(),QTreeWidgetItem::UserType);
        RecursionElement(root,rootitem);
        item->addChild(rootitem);
    }
    return true;
}

void Lib_XmlReadWrite::RecursionElement(XMLElement * element,QTreeWidgetItem* & item)
{
    //! 查找当前 element 子节点
    for (XMLElement* currentele = element->FirstChildElement(); currentele; currentele = currentele->NextSiblingElement())
    {
        XMLElement* tmpele = currentele;
        QTreeWidgetItem* childitem=new QTreeWidgetItem(QStringList()<<tmpele->Name()<<""<<tmpele->GetText());
        if(tmpele->FirstAttribute()!=NULL)
        {
            //! 添加属性值
            for (const XMLAttribute* var =tmpele->FirstAttribute(); var;var=var->Next()) {
                QTreeWidgetItem* attritem=new QTreeWidgetItem(QStringList()<<""<<var->Name()<<var->Value(),QTreeWidgetItem::UserType);
                attritem->setToolTip(2,var->Value());
                childitem->addChild(attritem);
            }
        }

        //! 查找 tmpele 子节点
        if (!tmpele->NoChildren())
            RecursionElement(tmpele,childitem);

        item->addChild(childitem);
    }
}

/*!
//! 调用
void MainWindow::LoadXMLStructure(QString text)
{
    ui->treeWidget->clear();
    ui->treeWidget->setHeaderLabels(QStringList()<<"节点"<<"属性"<<"业务值");
    ui->treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);

    if(text=="")
        return;

    QString ErrorStr;
    QTreeWidgetItem* item;
    bool isbol=Lib_XmlReadWrite::LoadTreeWidget(text,item,ErrorStr);

    if(!isbol)
    {
        qDebug()<<"[ErrorStr] "<<ErrorStr;
        ui->statusBar->showMessage(ErrorStr,0);
    }
    else
    {
        ui->treeWidget->addTopLevelItem(item);
        ui->treeWidget->expandAll();
    }
}
*/

效果:

其他TinyXML2库操作XML示例:

TinyXML2库解析xml感觉比Qt的QXmlStreamReader这种更好用,

但是不适合用来解析HTML文件,HTML文件中,像<link>这种节点会直接解析失败。

参考:

相关推荐
起名字真南11 分钟前
【OJ题解】C++实现字符串大数相乘:无BigInteger库的字符串乘积解决方案
开发语言·c++·leetcode
tyler_download23 分钟前
golang 实现比特币内核:实现基于椭圆曲线的数字签名和验证
开发语言·数据库·golang
小小小~23 分钟前
qt5将程序打包并使用
开发语言·qt
hlsd#23 分钟前
go mod 依赖管理
开发语言·后端·golang
小春学渗透25 分钟前
Day107:代码审计-PHP模型开发篇&MVC层&RCE执行&文件对比法&1day分析&0day验证
开发语言·安全·web安全·php·mvc
杜杜的man27 分钟前
【go从零单排】迭代器(Iterators)
开发语言·算法·golang
亦世凡华、28 分钟前
【启程Golang之旅】从零开始构建可扩展的微服务架构
开发语言·经验分享·后端·golang
测试界的酸菜鱼42 分钟前
C# NUnit 框架:高效使用指南
开发语言·c#·log4j
GDAL42 分钟前
lua入门教程 :模块和包
开发语言·junit·lua
李老头探索44 分钟前
Java面试之Java中实现多线程有几种方法
java·开发语言·面试