【零基础学QT】【039】Qt读写Xml

QXmlStreamReader读取XML
QXmlStreamReader按标签逐行读取XML文件,解析效率高,内存占用小
QXmlStreamReader在SAX解析的基础上,进行了接口简化
但是Qt仍然保留了SAX解析接口,因为SAX解析和DOM解析是两种公认的标准,方便用户从其它语言进行代码迁移


	//xml文件
	
	<doc date="2019-12-30">
	    <item name="A" id="1">
	        My Name is A
	    </item>
	    <item name="B" id="2">
	        My Name is B
	    </item>
	    <item name="C" id="3">
	        My Name is C
	    </item>
	</doc>


    //读取xml文件
    QFile file("C:/1.xml");
    file.open(QFile::ReadWrite);
    reader.setDevice(&file);
    QXmlStreamReader reader;

    //逐行读取,按类型打印
    while (!reader.atEnd()) {
        QXmlStreamReader::TokenType type = reader.readNext();
        switch (type) {
            case QXmlStreamReader::TokenType::StartDocument:
                qdebug << "Document Start" << endl;
                break;
            case QXmlStreamReader::TokenType::EndDocument:
                qdebug << "Document End" << endl;
                break;
            case QXmlStreamReader::TokenType::StartElement:
                qdebug << reader.name() << endl;
                qdebug << "id=" << reader.attributes().value("id") << endl;
                qdebug << "name=" << reader.attributes().value("name") << endl;
                break;
            case QXmlStreamReader::TokenType::EndElement:
                qdebug << reader.name() << endl;
                break;
            case QXmlStreamReader::TokenType::Characters:
                qdebug << reader.text().trimmed() << endl;
                break;
            default:
                break;
        }
    }

DOM读取XML
DOM解析先整个文档直接读入内存,转化为一个树类型的数据结构对象,再逐个遍历
DOM解析将文档操作转化为数据结构操作,更符合程序员思维,因此易于使用,特别是在一些复杂查找的情景下
但是由于DOM一次性加载整个文档,因此占用内存较大,不适合大型文档


	#include "qlib.h"
	
	//递归遍历DOM结点
	void parseDomElement(QDomNode node) {
	    //打印当前结点内容
	    QDomNode::NodeType type = node.nodeType();
	    switch (type) {
	        case QDomNode::NodeType::AttributeNode:
	            qdebug << node.toAttr().name() << "=" << node.toAttr().value() << endl;
	            break;
	        case QDomNode::NodeType::TextNode:
	            qdebug << node.toText().data().trimmed() << endl;
	            break;
	        case QDomNode::NodeType::ElementNode:
	            qdebug << node.toElement().tagName() << endl;
	            break;
	        default:
	            break;
	    }
	    //递归遍历子结点
	    QDomNodeList childNodeList = node.childNodes();
	    for (int i = 0; i < childNodeList.size(); i++) parseDomElement(childNodeList.at(i));
	    //打印结束标签
	    if (type == QDomNode::NodeType::ElementNode) qdebug << node.toElement().tagName() << endl;
	}
	
	int main(int argc, char* argv[]) {
	    QApplication app(argc, argv);
	
	    QMainWindow w;
	    w.show();
	
	    //设置字符编码
	    setlocale(LC_ALL, ".ACP");
	
	    //打开文件
	    QFile file("C:/1.xml");
	    file.open(QFile::ReadWrite);
	
	    //加载文件内容
	    QString errorMessage;
	    int errorLine;
	    int errorColumn;
	    QDomDocument doc;
	    doc.setContent(&file, &errorMessage, &errorLine, &errorColumn);
	
	    //解析文档
	    QDomElement rootElement = doc.documentElement();
	    parseDomElement(rootElement);
	
	    return app.exec();
	}

SAX读取XML
SAX逐行逐个元素读取XML,并且由用户手动控制解析流程,SAX解析的接口风格是明显的底层化风格
由于用户可以自己控制解析流程,因此不需要解析无用的数据,因此效率足够高
但是由于接口风格非常底层化,没有经过任何封装简化,所以使用起来代码比较繁琐
在Qt下,推荐使用QXmlStreamReader,它相当于优化版的SAX解析


    //设置字符编码
    setlocale(LC_ALL, ".ACP");

    //打开文件
    QFile file("C:/1.xml");
    file.open(QFile::ReadWrite);

    //XML处理器
    class SaxHandler : public QXmlDefaultHandler {
        bool startDocument() {
            qdebug << "document start" << endl;
            return true;
        }

        bool endDocument() {
            qdebug << "document end" << endl;
            return true;
        }

        bool startElement(
            const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts) {
            qdebug << localName << endl;
            for (int i = 0; i < atts.length(); i++) qdebug << atts.qName(i) << atts.value(i) << endl;
            return true;
        }

        bool endElement(const QString& namespaceURI, const QString& localName, const QString& qName) {
            qdebug << localName << endl;
            return true;
        }

        bool characters(const QString& ch) {
            qdebug << ch.trimmed() << endl;
            return true;
        }

    } handler;

    //开始解析
    QXmlSimpleReader reader;
    reader.setContentHandler(&handler);
    reader.parse(QXmlInputSource(&file));

QXmlStreamWriter写入XML
Qt写入XML主要有三种方式

  • 手动写入字符串
  • 在DOM解析中,修改QDomDocument 后,调用QDomDocument ::save保存修改
  • 使用QXmlStreamWriter

第一种只适合极其简单的文档,第二种适合先读再改,第三种适合重新创建一个XML文档
前两种不需要特意讲解,现在来讲使用QXmlStreamWriter来创建写入XML文档


    //打开文件
    QFile file("C:/2.xml");
    file.open(QFile::ReadWrite);

    //写入节点
    QXmlStreamWriter writer(&file);
    writer.setAutoFormatting(true);
    writer.writeStartDocument();
    writer.writeStartElement("doc");
    for (int i = 0; i < 3; i++) {
        writer.writeStartElement("item");
        writer.writeAttribute("id", "1");
        writer.writeAttribute("name", "A");
        writer.writeCharacters("This is a Xml Node");
        writer.writeEndElement();
    }
    writer.writeEndElement();
    writer.writeEndDocument();
    file.close();

发布了442 篇原创文章 · 获赞 45 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/u013718730/article/details/103594786
今日推荐