XML的基本介绍:
在前端开发中:HTML是用来显示数据,而XML是用来传输和存储数据的
- XML 指可扩展标记语言(EXtensible Markup Language)
- XML 是一种标记语言,很类似 HTML
- XML 的设计宗旨是传输数据,而非显示数据
- XML 标签没有被预定义。您需要自行定义标签。
- XML 被设计为具有自我描述性。
- XML 是 W3C 的推荐标准
XML 应用于 web 开发的许多方面,常用于简化数据的存储和共享。
- 通过 XML,可以在不兼容的系统之间轻松地交换数据。
- XML 独立于硬件、软件以及应用程序,XML 使您的数据更可用,也更有用。
- XML 数据以文本格式存储。这使得 XML 在不损失数据的情况下,更容易扩展或升级到新的操作系统、新应用程序或新的浏览器
在Qt中的XML:
使用Qt XML模块来对XML文档进行处理
- 使用DOM方法对XML文档进行读/写
- SAX方法对XML进行存取(这种方法已经过时)
- 从Qt5开始,使用Qt Core中的QXmlStreamReader和QXmlStreamWriter,使用流的方式对XML文档进行读写。
XML文件的介绍:
<? xml version="1.0" encoding="UTF-8"?>//XML说明,version版本号,encoding版本号
<root>//根元素
<id id="1">//元素 元素属性
<name>王老五</name>//元素 内容
</id>
<id id="2">
<name>张老四</name>
</id>
</root>//结束
xml的一些内容:
- 基本格式:<xxx>内容</xxx>
- XML有且仅有一个根元素 root
- 元素: root id name
- 属性格式: <元素 元素=”属性“>
- 内容:<元素>text</元素>
DOM中XML的表示:
XML说明 | QDomProcessingInstruction |
XML元素 | QDomElement |
XML 属性 | QDomAttr |
XML 内容 | QDomText |
全部同一使用 | QDomNode |
QDomNode
isProcessingInstruction() | 判断是否为xml说明 |
isElement() | 判断是否为xml元素 |
isAttr() | 判断是否为xml属性 |
isText() | 判断是否为xml内容 |
toProcessingInstruction() | 转化为xml说明 |
toElement() | 转化为xml元素 |
toAttr() | 转化为xml属性 |
toText() | 转化为xml内容 |
QDomDocument(Dom文档类)
使用QDomDocument表示整个XML文档,提供对文档数据的主要访问。
使用时需要在pro文件中添加:
QT += xml
常用的函数:
toString(int indent=1) | 将分析的文档转换为文本的形式表示,1为缩进 |
toByteArray(int indent=1) | 将分析的文档转换回其文本表示形式,1为缩进 |
setContent() | 此函数从字节数组数据分析 XML 文档,并将其设置为文档的内容。它尝试按照 XML 规范的要求检测文档的编码。 |
importNode() | 将节点导入节点从另一个文档导入到此文档。importedNode 保留在原始文档中;此函数创建可在此文档中使用的副本。 |
elementsByTagName() | 返回一个QDomNodeList,其中包含文档中具有名称标记名的所有元素。节点列表的顺序是它们在元素树的预序遍历中遇到的顺序。 |
elementById(QString id) | 返回根id匹配的元素 |
documentElement() | 返回文档的根元素 |
doctype() | 返回此文档的文档类型 |
createTextNode() | 为可以插入到文档树中的字符串值创建一个文本节点 |
createProcessingInstruction() | 创建一个可以插入到文档中的新处理指令 |
createEntityReference(name) | 创建一个名为 name 的新实体引用,可以插入到文档中 |
createElementNS() | 创建一个具有命名空间支持的新元素,该元素可以插入到 DOM 树中。 |
createElemrnt(tagname) | 创建一个名为 tagName 的新元素,可以插入到 DOM 树中 |
createComment() | 为可以插入到文档中的字符串值创建一个新注释 |
createAttributeNS() | 创建具有命名空间支持的新属性,该属性可以插入到元素中。 |
createAttribute(name) | 创建一个名为 name 的新属性,该属性可以插入到元素中 |
使用QDomDocument 读取xml中的数据:
- 创建一个QDomDocument对象
- 使用QFIle 打开xml文档
- 使用QDomDocument::setContent(file)把文件中的内容导入QDomDocument
- 使用QDocNode获取内容
首先创建一个xml文件,后缀为 .xml,然后把该文件添加到项目的资源文件中:
xml文件中添加以下代码:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<id id="1">
<name>wanglaowu</name>
</id>
<id id="2">
<name>zhanglaosi</name>
</id>
</root>
在main函数中添加以下代码:
#include <QApplication>
#include<QDomDocument>
#include<QMessageBox>
#include<QFile>
#include<QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDomDocument domdoc("myDom");//创建一个Dom文档对象
QFile file(":/new/prefix1/XMLtext.xml");
if(!file.open(QFile::ReadOnly))
{
QMessageBox::information(0,"提示信息","xml文件打开失败",QMessageBox::Ok);
return 0;
}
if(!domdoc.setContent(&file))//读取文件内容到domdoc
{
file.close();
return 0;
}
file.close();//读取完关闭文件
QDomNode firstNode=domdoc.firstChild();//获取第一个元素,XML说明
qDebug()<<qPrintable(firstNode.nodeName())//输出版本号
<<qPrintable(firstNode.nodeValue());//输出编码类型
return a.exec();
}
对于qPrintable的解释:
const char *qPrintable(const QString &str)
相当于:将 str 作为 .这相当于 str.toLocal8Bit().constData()
输出xml中的全部内容:
可以把XML看作一棵树:
QDomElement docElem=domdoc.documentElement();//获取根元素
QDomNode n=docElem.firstChild();//获取第一个子节点
while(!n.isNull())//不为空的话
{
if(n.isElement())//如果是元素的话
{
QDomElement e=n.toElement();//获取该元素
qDebug()<<qPrintable(e.tagName())//获取元素标记
<<qPrintable(e.attribute("id"));//id属性的值
QDomNodeList list=e.childNodes();//获取e的全部子节点
for(int i=0;i<list.count();i++)//遍历列表
{
QDomNode node=list.at(i);
if(node.isElement())
{
qDebug()<<" "<<qPrintable(node.toElement().tagName())//输出元素名
<<qPrintable(node.toElement().text());//输出内容
}
}
}
n=n.nextSibling();//转到下一个兄弟节点
}
创建一个XML文件并添加内容:
构建思路:
代码:
QDomDocument doc;//创建一个Dom对象
QDomProcessingInstruction instruction;//XML说明
instruction=doc.createProcessingInstruction
("xml","version=\"1.0\" encoding=\"UTF-8\"");//创建XML说明
doc.appendChild(instruction);//添加XML说明
//创建根元素
QDomElement root=doc.createElement("学生信息");
doc.appendChild(root);//添加根元素
//创建学生信息
QDomElement id=doc.createElement("学号");
QDomAttr number=doc.createAttribute("学号");//属性
QDomElement name=doc.createElement("姓名");
QDomElement age=doc.createElement("年龄");
QDomElement height=doc.createElement("身高");
QDomElement weight=doc.createElement("体重");
QDomText text;//内容
number.setValue(QString("1"));//设置学号的值
id.setAttributeNode(number);//id元素中添加number属性
//添加学生信息
text=doc.createTextNode("王一");
name.appendChild(text);
text=doc.createTextNode("15");
age.appendChild(text);
text=doc.createTextNode("160");
height.appendChild(text);
text=doc.createTextNode("40");
weight.appendChild(text);
//把这些信息添加到id元素中
id.appendChild(name);
id.appendChild(age);
id.appendChild(height);
id.appendChild(weight);
//将id添加到根元素中
root.appendChild(id);
//第二个学生
id=doc.createElement("学号");
number=doc.createAttribute("学号");//属性
name=doc.createElement("姓名");
age=doc.createElement("年龄");
height=doc.createElement("身高");
weight=doc.createElement("体重");
number.setValue(QString("2"));//设置学号
id.setAttributeNode(number);//id元素中设置number属性
//添加信息
text=doc.createTextNode("张三");
name.appendChild(text);
text=doc.createTextNode("16");
age.appendChild(text);
text=doc.createTextNode("165");
height.appendChild(text);
text=doc.createTextNode("45");
weight.appendChild(text);
//把这些信息添加到学号中
id.appendChild(name);
id.appendChild(age);
id.appendChild(height);
id.appendChild(weight);
//将id添加到根元素中
root.appendChild(id);
QFile file("my.xml");
if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))return;
QTextStream out(&file);
doc.save(out,4);//保存到out中,4格缩进
file.close();
打开该文件:
查找、修改、删除操作:
void Widget::find_updata_delete(const QString S)//
{
QFile file("my.xml");//打开该文件
if(!file.open(QFile::ReadOnly))
{
return;//打开失败的话退出
}
QDomDocument doc;
if(!doc.setContent(&file))//获取数据失败
{
file.close();
return;
}
//获取成功的话
QDomNodeList list=doc.elementsByTagName("学号");//获取标签
for(int i=0;i<list.count();i++)//遍历这些标签
{
QDomElement e=list.at(i).toElement();//获取元素
if(e.attribute("学号")==ui->lineEdit->text())//如果匹配成功的话
{
if(S=="delete")//删除操作的话
{
QDomElement root=doc.documentElement();//获取根节点
root.removeChild(list.at(i));//根节点中删除
QFile file("my.xml");
if(file.open(QIODevice::WriteOnly|QIODevice::Truncate))
return;
QTextStream out(&file);
doc.save(out,4);//保存到文件中
file.close();//关闭文件
}
else if(S=="updata")
{
QDomNodeList child=list.at(i).childNodes();//获取当前节点所有的子节点
child.at(0).toElement().firstChild().setNodeValue(ui->lineEdit_2->text());//更新姓名
child.at(1).toElement().firstChild().setNodeValue(ui->lineEdit_3->text());//更新年龄
child.at(2).toElement().firstChild().setNodeValue(ui->lineEdit_4->text());//更新身高
child.at(3).toElement().firstChild().setNodeValue(ui->lineEdit_5->text());//更新体重
QFile file("my.xml");
if(file.open(QIODevice::WriteOnly|QIODevice::Truncate))
return;
QTextStream out(&file);
doc.save(out,4);//保存到文件中
file.close();//关闭文件
}
else if(S=="find")
{
qDebug()<<e.tagName()<<" "<<e.attribute("学号");//输出元素名和学号
QDomNodeList nodeList=e.childNodes();//获取内容节点
for(int i=0;i<nodeList.count();i++)
{
QDomNode node=nodeList.at(i);
if(node.isElement())
{
qDebug()<<node.toElement().tagName()<<" "<<node.toElement().text();//输出元素名和内容
}
}
}
}
}
}
void Widget::on_pushButton_clicked()//查找
{
find_updata_delete("find");
}
运行结果:
以上是Dom简单使用xml的方法。(感觉有点繁琐)
XML流
从Qt 4.3开始引入两个新类来读取和写入XML文档:
QXmlStreamReader类:
- 是一个快速的解析器,使用简单的流API来读取格式良好的XML文档
- QXmlStreamReader可以从QIODevice或QByteArray中读取数据
- 流读取器:将XML文档报告为一个记号流,使用程序代码自身来驱动循环,在需要的时候可以从读取器中一个接着一个地拉出记号,使用readNext()函数获取记号
QXmlStreamReader::TokenType:
常量 | 描述 |
QXmlStreamReader::NoToken | 没有读过任何东西。 |
QXmlStreamReader::Invalid | 使用error()和errorString()中报告错误 |
QXmlStreamReader::StartDocument | 在documentVersion()中报告XML版本号,使用documentEncoding()中指定文档的编码 |
QXmlStreamReader::EndDocument | 报告文档结束 |
QXmlStreamReader::StartElement | 使用namespaceUri()和name()来报告元素开始,可以使用attributes()来获取属性 |
QXmlStreamReader::EndElement | 使用nameSpaceUri()和name()来报告元素结束 |
QXmlStreamReader::Characters | 使用text()来报告字符,如果字符是空白,那么isWhitespace()返回true,如果字符源于CDATA部分,那么isCDATA()返回true |
QXmlStreamReader::Comment | 使用在text()中报告注释 |
QXmlStreamReader::DTD | 使用在 text() 中报告 DTD,在 notationDeclDeclarations() 中报告表示法声明,在 entityDeclarations() 中报告实体声明。DTD 声明的详细信息在 dtdName()、dtdPublicid和dtdSystemid() 中报告 |
QXmlStreamReader::EntityReference | 报告无法解析的实体引用。引用的名称在 name() 中报告,替换文本在 text() 中报告。 |
QXmlStreamReader::ProcessingInstruction | 使用processingInstruction Target()和processingInstruction Data()中报告处理指令 |
使用QXmlStreamReader读取xml文档:
具体流程:
- 先打开文件 file
- 创建一个阅读器,使用setDevice()设置读取对象
- 使用readNext()读取一个记号
- 使用读取的记号进行判断
#include <QApplication>
#include<QXmlStreamReader>
#include<QFile>
#include<QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFile file(":/new/xml/my.xml");
if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
{
return 0;
}
QXmlStreamReader reader;//创建一个阅读器
reader.setDevice(&file);//设置需要读取的文件
while(!reader.atEnd())//如果不到结尾
{
QXmlStreamReader::TokenType type=reader.readNext();//获取一个记号
if(type==QXmlStreamReader::StartDocument)//读取XML说明
{
qDebug()<<reader.documentVersion()<<" "<<reader.documentEncoding();//读取版本号和编码类型
}
if(type==QXmlStreamReader::StartElement)//获取元素
{
qDebug()<<reader.name();//获取元素名
if(reader.attributes().hasAttribute("id"))//如果有属性
{
qDebug()<<reader.attributes().value("id");//输出属性
}
}
if(type==QXmlStreamReader::EndElement)//获取结束元素
{
qDebug()<<reader.name();
}
if(type==QXmlStreamReader::Characters&&!reader.isWhitespace())
{
qDebug()<<reader.text();//读取内容
}
}
if(reader.hasError())
{
qDebug()<<"error:"<<reader.errorString();
}
file.close();//关闭文件
return a.exec();
}
QXMLStreamWriter
用于编写XML文档
常用函数:
setAutoFormatting() | 设置自动化类型 |
hasError() | 写入失败返回true |
setCodec() | 设置解码器,默认使用UTF-8 |
setDevice() | 设置写入的设备 |
writeTextElement() | 写入带有内容的元素 |
writeStartElement() | 写入起始元素 |
writeStartDocument() | 写入XML版本号和编码信息 |
writeProcessingInstruction() | 编写包含目标和数据 XML 处理指令 |
writeNamespace() | 为带有前缀的命名空间 Uri 编写命名空间声明 |
writeEndElement() | 关闭上一个开始元素 |
writeEndDocument() | 关闭所有剩余的打开开始元素并写入换行符 |
writeEmptyElement() | 写入一个带有名称的空元素 |
writeDTD() | 写入 DTD 节 |
writeAttributes() | 写入属性 |
例子:
QFile file("Myxml.xml");
if(!file.open(QIODevice::WriteOnly|QIODevice::Text))
{
return 0;
}
QXmlStreamWriter Writer;
Writer.setDevice(&file);//获取流
Writer.setAutoFormatting(true);
Writer.writeStartDocument();//添加XML说明(版本号和编码信息
Writer.writeStartElement("student");//写入起始元素
Writer.writeStartElement("id");
Writer.writeAttribute("id","1");//写入属性
Writer.writeTextElement("name","王维");
Writer.writeTextElement("age","15");
Writer.writeTextElement("height","165");
Writer.writeTextElement("weight","50");
Writer.writeEndElement();//结束id元素编辑
Writer.writeEndElement();//结束student元素编辑
Writer.writeEndDocument();//结束整个的编辑
file.close();//关闭文件
参考文档:
XML 的用途 (w3school.com.cn)
XML Processing | Qt XML 5.15.12