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 < 1000 then</message>
在XML中,有 5 個預定義的實體引用,如下表所示:
< | < | less than |
> | > | greater than |
& | & | ampersand |
' | ' | apostrophe |
" | " | quotation mark |
在 XML 中編寫注釋的文法與 HTML 的文法很相似,采用<!-- 注釋内容 -->的方式;
在 XML 中,文檔中的空格不會被删減。
2、功能說明
目前根據需要初步實作如下功能,後續會根據需要會添加一些新功能和案例!
1)從XML文檔/字元串讀取資料--F1GetDocumentFromFile、F2GetDocumentFromStr
2)輸出XML資料--M1LoadXmlFromDoc
3)擷取某元素最外層所有屬性--M2GetAllAttributes
4)擷取某元素子層的所有元素--M3GetAllSubNodes
5)建立一個XML--M4CreateXML
6)将XML儲存到本地--M5SaveXML
3、源代碼
3.1 XML
代碼包括三個主要檔案: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、XML案例
5.1、構造XML案例1
該案例主要用于生成如下XML文檔,其具體内容和源碼如下:
XML文檔内容:
<?xml version="1.0" encoding="UTF-8"?>
<!--This is Two Jobs Nested->JDF_INPUT->20150609112433.jdf-->
<JDF JobID="20150609112433" JobPartID="1" Activation="Active" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cal="http://www.caldera.com/jdf" xmlns="http://www.CIP4.org/JDFSchema_1_1" Version="1.4" Type="DigitalPrinting" ID="20150609112433" Status="Waiting" ICSVersions="Base_L1-1.4" DescriptiveName="20150609112433">
<Comment Name="JobDescription"/>
<ResourcePool>
<RunList Class="Parameter" DocCopies="2" ID="RL001" Status="Available">
<LayoutElement>
<FileSpec URL="file://FILES/20150609112433/FlameBoy_Cut.eps"/>
</LayoutElement>
</RunList>
<DigitalPrintingParams Class="Parameter" ID="DPP001" Status="Available"/>
<CustomerInfo CustomerOrderID="" Class="Parameter" CustomerID="ORDER001" ID="CI001" Status="Available">
<Contact ContactTypes="Sales">
<Address Street="1 rue des frères lumières" City="xxx" Country="France" PostalCode="xxx"/>
<Company OrganizationName=""/>
<ComChannel ChannelType="Phone" Locator="tel:+xxxx"/>
<ComChannel ChannelType="Fax" Locator="tel:+xxx"/>
<Person Languages="EN" JobTitle="Manager" FirstName="">
<Address Street="1 rue des xxx" City="Strasbourg" Country="France" PostalCode="xxxx"/>
<ComChannel ChannelType="Email" Locator="mailto:[email protected]"/>
</Person>
</Contact>
</CustomerInfo>
<Device Class="Implementation" DeviceID="CalderaJet:Nest" ID="DEV001" Status="Available"/>
<Component Class="Quantity" ID="C001" Status="Unavailable" ComponentType="FinalProduct"/>
</ResourcePool>
<ResourceLinkPool>
<DigitalPrintingParamsLink Usage="DPP001"/>
<RunListLink Usage="Input" rRef="RL001"/>
<CustomerInfoLink Usage="Input" ref="CI001"/>
<DeviceLink Usage="Input" rRef="DEV001"/>
<ComponentLink Usage="Input" rRef="C001"/>
</ResourceLinkPool>
<AuditPool>
<Created AgentVersion="10.0" AgentName="Caldera JDF" TimeStamp="2015-06-09T11:24:33+02:00"/>
</AuditPool>
</JDF>
源碼:
QDomDocument JtCreateJDF();
void JtTestCreateJDF();
void JtSaveJDF();
QDomDocument XmlClass::JtCreateJDF()
{
QDomDocument doc;
//1)添加聲明
QDomProcessingInstruction DPI = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
doc.appendChild(DPI);
//2)添加注釋
QDomComment DC = doc.createComment("This is Two Jobs Nested->JDF_INPUT->20150609112433.jdf");
doc.appendChild(DC);
//3)添加根元素JDF
QDomElement DE = doc.createElement("JDF");
DE.setAttribute("xmlns:cal","http://www.caldera.com/jdf");//添加屬性
DE.setAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
DE.setAttribute("ID","20150609112433");
DE.setAttribute("JobID","20150609112433");
DE.setAttribute("JobPartID","1");
DE.setAttribute("Status","Waiting");
DE.setAttribute("Activation","Active");
DE.setAttribute("Type","DigitalPrinting");
DE.setAttribute("Version","1.4");
DE.setAttribute("ICSVersions","Base_L1-1.4");
DE.setAttribute("DescriptiveName","20150609112433");
DE.setAttribute("xmlns","http://www.CIP4.org/JDFSchema_1_1");
doc.appendChild(DE);
//4-1)添加子元素Comment
QDomElement DE1 = doc.createElement("Comment");
DE1.setAttribute("Name","JobDescription");
DE.appendChild(DE1);
//4-2)添加子元素ResourcePool
QDomElement DE2 = doc.createElement("ResourcePool");
QDomElement DE21 = doc.createElement("RunList");
DE21.setAttribute("Class","Parameter");
DE21.setAttribute("ID","RL001");
DE21.setAttribute("Status","Available");
DE21.setAttribute("DocCopies","2");
QDomElement DE211 = doc.createElement("LayoutElement");
QDomElement DE2111 = doc.createElement("FileSpec");
DE2111.setAttribute("URL","file://FILES/20150609112433/FlameBoy_Cut.eps");
DE211.appendChild(DE2111);
DE21.appendChild(DE211);
QDomElement DE22 = doc.createElement("DigitalPrintingParams");
DE22.setAttribute("Class","Parameter");
DE22.setAttribute("ID","DPP001");
DE22.setAttribute("Status","Available");
QDomElement DE23 = doc.createElement("CustomerInfo");
DE23.setAttribute("Class","Parameter");
DE23.setAttribute("ID","CI001");
DE23.setAttribute("Status","Available");
DE23.setAttribute("CustomerID","ORDER001");
DE23.setAttribute("CustomerOrderID","");
QDomElement DE231 = doc.createElement("Contact");
DE231.setAttribute("ContactTypes","Sales");
QDomElement DE2311 = doc.createElement("Address");
DE2311.setAttribute("City","xxx");
DE2311.setAttribute("Country","France" );
DE2311.setAttribute("PostalCode","xxx" );
DE2311.setAttribute("Street","1 rue des frères lumières");
QDomElement DE2312 = doc.createElement("Company");
DE2312.setAttribute("OrganizationName","");
QDomElement DE2313 = doc.createElement("ComChannel");
DE2313.setAttribute("ChannelType","Phone");
DE2313.setAttribute("Locator","tel:+xxxx");
QDomElement DE2314 = doc.createElement("ComChannel");
DE2314.setAttribute("ChannelType","Fax");
DE2314.setAttribute("Locator","tel:+xxx");
QDomElement DE2315 = doc.createElement("Person");
DE2315.setAttribute("FirstName","");
DE2315.setAttribute("JobTitle","Manager");
DE2315.setAttribute("Languages","EN");
QDomElement DE23151 = doc.createElement("Address");
DE23151.setAttribute("City","Strasbourg");
DE23151.setAttribute("Country","France");
DE23151.setAttribute("PostalCode","xxxx");
DE23151.setAttribute("Street","1 rue des xxx");
QDomElement DE23152 = doc.createElement("ComChannel");
DE23152.setAttribute("ChannelType","Email");
DE23152.setAttribute("Locator","mailto:[email protected]");
DE2315.appendChild(DE23151);
DE2315.appendChild(DE23152);
DE231.appendChild(DE2311);
DE231.appendChild(DE2312);
DE231.appendChild(DE2313);
DE231.appendChild(DE2314);
DE231.appendChild(DE2315);
DE23.appendChild(DE231);
QDomElement DE24 = doc.createElement("Device");
DE24.setAttribute("Class","Implementation");
DE24.setAttribute("ID","DEV001");
DE24.setAttribute("Status","Available");
DE24.setAttribute("DeviceID","CalderaJet:Nest");
QDomElement DE25 = doc.createElement("Component");
DE25.setAttribute("Class","Quantity");
DE25.setAttribute("ID","C001");
DE25.setAttribute("Status","Unavailable");
DE25.setAttribute("ComponentType","FinalProduct");
DE2.appendChild(DE21);
DE2.appendChild(DE22);
DE2.appendChild(DE23);
DE2.appendChild(DE24);
DE2.appendChild(DE25);
DE.appendChild(DE2);
//4-3)添加子元素ResourceLinkPool
QDomElement DE3 = doc.createElement("ResourceLinkPool");
QDomElement DE31 = doc.createElement("DigitalPrintingParamsLink");
DE31.setAttribute("Usage","Input");
DE31.setAttribute("Usage","DPP001");
QDomElement DE32 = doc.createElement("RunListLink");
DE32.setAttribute("Usage","Input");
DE32.setAttribute("rRef","RL001");
QDomElement DE33 = doc.createElement("CustomerInfoLink");
DE33.setAttribute("Usage","Input");
DE33.setAttribute("ref","CI001");
QDomElement DE34 = doc.createElement("DeviceLink");
DE34.setAttribute("Usage","Input");
DE34.setAttribute("rRef","DEV001");
QDomElement DE35 = doc.createElement("ComponentLink");
DE35.setAttribute("Usage","Input");
DE35.setAttribute("rRef","C001");
DE3.appendChild(DE31);
DE3.appendChild(DE32);
DE3.appendChild(DE33);
DE3.appendChild(DE34);
DE3.appendChild(DE35);
DE.appendChild(DE3);
//4-4)添加子元素AuditPool
QDomElement DE4 = doc.createElement("AuditPool");
QDomElement DE41 = doc.createElement("Created");
DE41.setAttribute("AgentName","Caldera JDF");
DE41.setAttribute("AgentVersion","10.0");
DE41.setAttribute("TimeStamp","2015-06-09T11:24:33+02:00");
DE4.appendChild(DE41);
DE.appendChild(DE4);
return doc;
}
void XmlClass::JtTestCreateJDF()
{
QDomDocument doc = JtCreateJDF();
//qDebug().noquote()<<'\n\n'<<doc.documentElement().tagName()<<":";
qDebug().noquote()<<doc.toString(2);
}
void XmlClass::JtSaveJDF()
{
/*
* 該函數用于将JDF儲存到本地
*/
QString PathName="JDF_I_20150609112433.jdf";
QDomDocument doc = JtCreateJDF();
if(!doc.isNull()){
QFile file(PathName);
if(file.open(QFile::WriteOnly|QFile::Text))
{
QTextStream out(&file);
doc.save(out,4,QDomNode::EncodingFromDocument);
file.close();
qDebug()<<"\nSave JDF Done!";
}else
{
qDebug()<<"Open File Error!";
}
}else{
qDebug()<<"doc is NULL!";
}
}
6、說明
以上代碼預設測試環境為Qt 5.7,測試系統為Windows7 x64