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、源代码
代码包括三个主要文件: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