Qt 笔记3--Qt 操作 XML

Qt 笔记3--Qt 操作 XML

XML 可扩展标记语言(eXtensible Markup Language),被设计用来传输和存储数据,是当前使用最广泛的网络数据传输格式之一。

Qt提供了一系列基于DOM的XML处理类,包括:QDomComment、QDomProcessingInstruction、QDomComment、QDomElement、QDomText、QDomDocumentType、QDomNodeList等 ,以下为笔者最近学习Qt XML解析功能时写的一些用例,相应学习笔记分享在此处,以便于后续参考。若后续有新的功能或者案例,也会在此处加以补充!

1、XML基础知识

XML 可扩展标记语言(eXtensible Markup Language),被设计用来传输和存储数据。

1.1 XML 结构

<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

第一行是 XML 声明。它定义 XML 的版本(1.0)和所使用的编码;
第二行描述文档的根元素;
接下来 4 行描述根的 4 个子元素(to, from, heading 以及 body);
最后一行定义根元素的结尾。

XML 文档形成一种树结构;
XML 文档必须包含根元素,该元素是所有其他元素的父元素;
XML 文档中的元素形成了一棵文档树。这棵树从根部开始,并扩展到树的最底端;
所有的元素都可以有子元素;父、子以及同胞等术语用于描述元素之间的关系,父元素拥有子元素,相同层级上的子元素成为同胞(兄弟或姐妹),所有的元素都可以有文本内容和属性。

1.2 XML语法规则

XML 必须包含根元素,它是所有其他元素的父元素;
XML的声明是可选部分,如果存在需要放在文档的第一行,一般标注版本、编码等信息;
在XML中,省略关闭标签是非法的,所有元素都必须有关闭标签,其中声明不是XML正文的一部分,它没有标签;
XML标签对大小写敏感,必须使用相同的大小写来编写打开标签和关闭标签;
XML中所有元素都必须彼此正确地嵌套,若A嵌套在B中,那么A的开始和结束都需要在B中;
XML 属性值必须加引号;XML中,一些字符拥有特殊的意义,如果把字符 "<" 放在XML元素中,会发生错误,这是因为解析器会把它当作新元素的开始,为了避免这个错误,请用实体引用来代替 "<" 字符,例如:为了避免<字符带来的错误,需要将
<message>if salary < 1000 then</message>
替换为:
<message>if salary &lt; 1000 then</message>
在XML中,有 5 个预定义的实体引用,如下表所示:

&lt

< less than
&gt; > greater than
&amp; & ampersand
&apos; ' apostrophe
&quot; " quotation mark

在 XML 中编写注释的语法与 HTML 的语法很相似,采用<!-- 注释内容 -->的方式;
在 XML 中,文档中的空格不会被删减。

2、功能说明

当前根据需要初步实现如下功能,后续会根据需要会添加一些新功能和案例!

1)从XML文档/字符串读取数据--F1GetDocumentFromFile、F2GetDocumentFromStr
2)输出XML数据--M1LoadXmlFromDoc
3)获取某元素最外层所有属性--M2GetAllAttributes
4)获取某元素子层的所有元素--M3GetAllSubNodes
5)创建一个XML--M4CreateXML
6)将XML保存到本地--M5SaveXML

3、源代码

代码包括三个主要文件:xmlclass.h、xmlclass.cpp、main.cpp,源码如下:

xmlclass.h

#ifndef XMLCLASS_H
#define XMLCLASS_H

#include <QObject>
#include <QDebug>
#include <QFile>
#include <QList>

#include <QDomDocument>
#include <QDomDocumentType>
#include <QDomElement>
#include <QDomNodeList>

class XmlClass
{
public:
    XmlClass();
    QDomDocument F1GetDocumentFromFile(QString PathName);
    QDomDocument F2GetDocumentFromStr(QString XMLstr);
    void TestF2GetDocumentFromStr();
    void M1LoadXmlFromDoc(QString PathName);
    void TestM1LoadXmlFromDoc();
    void M2GetAllAttributes(QDomElement de);
    void TestM2GetAllAttributes();
    QList<QDomElement> M3GetAllSubNodes(QDomElement de);
    void TestM3GetAllSubNodes();
    QDomDocument M4CreateXML();
    void TestM4CreateXML();
    void M5SaveXML(QDomDocument de,QString PathName);
    void TestM5SaveXML();
};

#endif // XMLCLASS_H

xmlclass.cpp

#include "xmlclass.h"

XmlClass::XmlClass()
{
    qDebug()<<"Initial XmlClass!";
}

QDomDocument XmlClass::F1GetDocumentFromFile(QString PathName)
{
    /*
    * 该函数用于从某个文件读取XML,并返回document对象
    */
    QDomDocument doc;
    QFile file(PathName);
    if(!file.open(QIODevice::ReadOnly))
    {
        qDebug()<<"Read file error!";
    }
    if(!doc.setContent(&file))
    {
        qDebug()<<"SetContent Error!";
        file.close();
    }
    file.close();
    return doc;
}

QDomDocument XmlClass::F2GetDocumentFromStr(QString XMLstr)
{
    /*
    * 该函数用于从XMLStr中读取XML,并返回QDomDocument对象
    */
    qDebug()<<"\nF2:Get Document From Str!";
    qDebug().noquote()<<"XMLStr:"<<XMLstr;
    QDomDocument doc;
    doc.setContent(XMLstr);
    return doc;
}

void XmlClass::TestF2GetDocumentFromStr()
{
    QString xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>";
    QDomDocument doc = F2GetDocumentFromStr(xmlStr);
    if(!doc.isNull()){
        qDebug().noquote()<<doc.toString(2);//default indent is 1
    }else{
        qDebug()<<"Load XML From String Error!";
    }
}

void XmlClass::M1LoadXmlFromDoc(QString PathName)
{
    /*
    * 该函数用于从某个文件读取XML并输出
    */
    qDebug()<<"\nM1:Load XML!";
    QDomDocument doc = F1GetDocumentFromFile(PathName);
    if(!doc.isNull()){
        qDebug().noquote()<<doc.toString(2);//default indent is 1
    }else{
        qDebug()<<"Load XML Error!";
    }
}

void XmlClass::TestM1LoadXmlFromDoc()
{
    M1LoadXmlFromDoc("20150609094727.jdf");
}

void XmlClass::M2GetAllAttributes(QDomElement de)
{
    /*
    * 该函数用于获取某个元素的最外层所有属性
    */
    qDebug()<<"\nM2:Get All Attributes!";
    if(!de.isNull())
    {
        qDebug().noquote()<<de.tagName()<<" attributes:";
        QDomNamedNodeMap dnn = de.attributes();
        for(int i=0;i<dnn.size();i++)
        {
            QDomNode dn = dnn.item(i);
            qDebug().noquote()<<dn.nodeName()<<":"<<dn.nodeValue();
        }
    }
}

void XmlClass::TestM2GetAllAttributes()
{
    QString PathName = "20150609094727.jdf";
    QDomDocument doc = F1GetDocumentFromFile(PathName);
    if(!doc.isNull()){
        QDomElement de = doc.documentElement();
        M2GetAllAttributes(de);
    }else
    {
        qDebug()<<"Load XML Error!";
    }
}

QList<QDomElement>  XmlClass::M3GetAllSubNodes(QDomElement de)
{
    /*
    * 该函数用于获取某个元素的子层所元素,并输出子层所有元素的tagname
    */
    qDebug()<<"\nM3:Get All SubNodes!";
    QList<QDomElement> DeList;
    for(QDomNode n=de.firstChild();!n.isNull();n=n.nextSibling())
    {
        QDomElement tmp = n.toElement();
        DeList.append(tmp);
    }
    return DeList;
}

void XmlClass::TestM3GetAllSubNodes()
{
    QString PathName = "20150609094727.jdf";
    QDomDocument doc = F1GetDocumentFromFile(PathName);
    if(!doc.isNull()){
        QDomElement de = doc.documentElement();
        QList<QDomElement> DeList = M3GetAllSubNodes(de);
        qDebug()<<"DeList Size:"<<DeList.size();
        for(int i=0;i<DeList.size();i++)
        {
            QDomElement tmp = DeList[i];
            if(tmp.text()!=NULL){
                qDebug().noquote()<<tmp.tagName()<<":"<<tmp.text();
            }else{
                qDebug().noquote()<<tmp.tagName();
            }
        }
    }else
    {
        qDebug()<<"Load XML Error!";
    }
}

QDomDocument XmlClass::M4CreateXML()
{
    /*
    * 该函数用于创建一个XML
    * 创建内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- This is a comment -->
<note Attr="note attr">
    <to>Tove</to>
    <from>Jani</from>
    <date ymd="2019-03-29" />
    <heading>Reminder</heading>
    <body AttrH="300" AttrW="600">Don't forget me this weekend!</body>
</note>
    */
    qDebug()<<"\nM4:Create XML!";
    QDomDocument doc;
    //1)添加声明
    QDomProcessingInstruction DPI = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
    doc.appendChild(DPI);
    //2)添加注释
    QDomComment DC = doc.createComment("This is a comment");
    doc.appendChild(DC);
    //3)添加根元素note
    QDomElement DE = doc.createElement("note");
    DE.setAttribute("Atte","note attr");//添加属性
    doc.appendChild(DE);
    //4-1)添加子元素to
    QDomElement DE1 = doc.createElement("to");
    QDomText DT1 = doc.createTextNode("Tove");
    DE1.appendChild(DT1);
    DE.appendChild(DE1);
    //4-2)添加子元素from
    QDomElement DE2 = doc.createElement("from");
    QDomText DT2 = doc.createTextNode("Jani");
    DE2.appendChild(DT2);
    DE.appendChild(DE2);
    //4-3)添加子元素date
    QDomElement DE3 = doc.createElement("date");
    DE3.setAttribute("ymd","2019-03-29");
    DE.appendChild(DE3);
    //4-4)添加子元素heading
    QDomElement DE4 = doc.createElement("heading");
    QDomText DT4 = doc.createTextNode("Reminder");
    DE4.appendChild(DT4);
    DE.appendChild(DE4);
    //4-5)添加子元素body
    //<body AttrH="300" AttrW="600">Don't forget me this weekend!</body>
    QDomElement DE5 = doc.createElement("body");
    DE5.setAttribute("AttrH","300");
    DE5.setAttribute("AttrW","600");
    QDomText DT5 = doc.createTextNode("Don't forget me this weekend!");
    DE4.appendChild(DT5);
    DE.appendChild(DE5);
    return doc;
}

void XmlClass::TestM4CreateXML()
{
    QDomDocument doc = M4CreateXML();
    qDebug().noquote()<<doc.documentElement().tagName()<<"info:";
    qDebug().noquote()<<doc.toString(2);
}

void XmlClass::M5SaveXML(QDomDocument de,QString PathName)
{
    /*
    * 该函数用于将XML保存到本地
    */
    QFile file(PathName);
    if(file.open(QFile::WriteOnly|QFile::Text))
    {
        QTextStream out(&file);
        de.save(out,QDomNode::EncodingFromDocument);
        file.close();
        qDebug()<<"\nM5:Save XML Done!";
    }else
    {
        qDebug()<<"M5:Open File Error!";
    }
}

void XmlClass::TestM5SaveXML()
{
    qDebug()<<"\nM5:Save XML!";
    QString xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>";
    QDomDocument doc = F2GetDocumentFromStr(xmlStr);
    if(!doc.isNull()){
        M5SaveXML(doc,"Tmp.xml");
    }else{
        qDebug()<<"Load XML From String Error!";
    }
}

main.cpp

#include <QCoreApplication>
#include "xmlclass.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    XmlClass *XCobj = new XmlClass();
    XCobj->TestF2GetDocumentFromStr();
    XCobj->TestM1LoadXmlFromDoc();
    XCobj->TestM2GetAllAttributes();
    XCobj->TestM3GetAllSubNodes();
    XCobj->TestM4CreateXML();
    XCobj->TestM5SaveXML();
    delete XCobj;

    return a.exec();
}

4、测试结果

1)从XML文档/字符串读取数据--F1GetDocumentFromFile、F2GetDocumentFromStr

F2:Get Document From Str!
XMLStr: <?xml version="1.0" encoding="UTF-8"?><note><to>Tove</to><from>Jani</fro
m><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>
<?xml version='1.0' encoding='UTF-8'?>
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

2)输出XML数据--M1LoadXmlFromDoc

M1:Load XML!
<?xml version='1.0' encoding='utf-8'?>
<JDF ICSVersions="Base_L1-1.4" **此处省略部分内容** Activation
="Active">
  <Comment Name="JobDescription"/>
** 此处省略一部分内容**
  <AuditPool>
    <Created AgentName="Caldera JDF" AgentVersion="10.0" TimeStamp="2015-06-09T0
9:47:27+02:00"/>
  </AuditPool>
</JDF>

3)获取某元素最外层所有属性--M2GetAllAttributes

M2:Get All Attributes!
JDF  attributes:
ICSVersions : Base_L1-1.4
Type : DigitalPrinting
Version : 1.4
DescriptiveName : 20150609094727
Status : Waiting
xmlns:xsi : http://www.w3.org/2001/XMLSchema-instance
ID : 20150609094727
xmlns:cal : http://www.caldera.com/jdf
JobPartID : 1
xmlns : http://www.CIP4.org/JDFSchema_1_1
JobID : 20150609094727
Activation : Active

4)获取某元素子层的所有元素--M3GetAllSubNodes

M3:Get All SubNodes!
DeList Size: 4
Comment
ResourcePool
ResourceLinkPool
AuditPool

5)创建一个XML--M4CreateXML

M4:Create XML!
note info:
<?xml version="1.0" encoding="UTF-8"?>
<!--This is a comment-->
<note Atte="note attr">
  <to>Tove</to>
  <from>Jani</from>
  <date ymd="2019-03-29"/>
  <heading>ReminderDon't forget me this weekend!</heading>
  <body AttrW="600" AttrH="300"/>
</note>

6)将XML保存到本地--M5SaveXML

M5:Save XML!

F2:Get Document From Str!
XMLStr: <?xml version="1.0" encoding="UTF-8"?><note><to>Tove</to><from>Jani</fro
m><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>

M5:Save XML Done!

5、说明

以上代码默认测试环境为Qt 5.7,测试系统为Windows7 x64

参考文献:
[1] Qt 之 XML(DOM): https://blog.csdn.net/liang19890820/article/details/52981488 
[2] QtDocumentation QDom* : https://doc.qt.io/qt-5/classes.html#d
[3] XML 教程 : http://www.runoob.com/xml/xml-tutorial.html
[4] XML 在线解析工具 : https://c.runoob.com/front-end/710

猜你喜欢

转载自blog.csdn.net/u011127242/article/details/88779457