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

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

码农世界 2024-05-27 前端 71 次浏览 0个评论

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

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

目录导读

    • Tinyxml2库 介绍(文言一心)
    • 使用CMAKE 和 MSVC 2017 编译 Tinyxml2库
    • QT 调用 **tinyxml2.lib** 解析XML
      • 遍历所有节点
      • 将XML节点 加载到QTreeWidget 控件上
      • 其他TinyXML2库操作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平台:

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

          项目工程直接生成 tinyxml2.lib 没有了dll文件。

          xmltest.cpp 文件为调用示例,建议参考。

          QT 调用 tinyxml2.lib 解析XML

          将项目中的 tinyxml2.h 和 tinyxml2.cpp ,tinyxml2.lib 放在项目目录下。

          #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遍历所有节点

          #include 
          #include 
          #include 
          #include 
          #include 
          #include 
          #include 
          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()<<"---->" <Name()<<" : "<Value();
                      }
                  }
          		
          		//! 有子节点继续加载
                  if (!tmpele->NoChildren())
                      GetEleValue(tmpele);
              }
          }
          void Lib_XmlReadWrite::LoadXML(QString xml)
          {
              QFileInfo info("C:\\Users\\admin\\Desktop\\textxml\\text_xml5.xml");
              qDebug()<< "LoadXML -->"<FirstChildElement()->Name();
              qDebug()<Name();
              qDebug()<<"-----------------------------------";
              GetEleValue(doc.RootElement());
          }
          

          将XML节点 加载到QTreeWidget 控件上

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

          值得注意的是 如果一个文件有多个根节点可以通过

          for (XMLElement* root = doc.RootElement(); root; root = root->NextSiblingElement())

          遍历所有根节点。

          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()<NextSiblingElement())
              {
                  //! XML子节点
                  QTreeWidgetItem* rootitem=new QTreeWidgetItem(QStringList()<Name())<<""<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()<Name()<<""<GetText());
                  if(tmpele->FirstAttribute()!=NULL)
                  {
                      //! 添加属性值
                      for (const XMLAttribute* var =tmpele->FirstAttribute(); var;var=var->Next()) {
                          QTreeWidgetItem* attritem=new QTreeWidgetItem(QStringList()<<""<Name()<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] "<statusBar->showMessage(ErrorStr,0);
              }
              else
              {
                  ui->treeWidget->addTopLevelItem(item);
                  ui->treeWidget->expandAll();
              }
          }
          */
          

          效果:

          其他TinyXML2库操作XML示例:

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

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

          参考:

          • TinyXML2使用方法及示例
          • 官方示例 xmltest.cpp 文件

转载请注明来自码农世界,本文标题:《QT调用Tinyxml2库解析XML结构文件》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,71人围观)参与讨论

还没有评论,来说两句吧...

Top