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>这种节点会直接解析失败。

参考:

相关推荐
用户805533698031 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner1 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz6 天前
QML Hello World 入门示例
qt
xcyxiner9 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner10 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner10 天前
DicomViewer (添加模型类)3
qt
xcyxiner11 天前
DicomViewer (目录调整) 2
qt
xcyxiner11 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00613 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术13 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript