【Qt】解析XML

        XML是一种常见且常用的文档格式。当然,Qt自然也囊括了解析XML相关的模块和类。为了方便以后自己或其他人遇到相关问题时查阅,下面将Qt中解析XML的常见方式罗列出来。

如果不使用第三方的解析库的话,需要在qt的项目文件中加入Qt += xml

Qt中解析XML的方法

1使用Qt的内置XML模块QDomDocument,这个模块提供了一种解析和操作XML文档的方式,可用于读取和操作XML文档。可以使用QDomDocument类来解析XML文档,并使用其他相关类来遍历和操作XML树结构,例如QDomNode、QDomElement和QDomText等。
2QXmlStreamReader
QXmlStreamWriter
StreamReader,这个模块提供了一种使用流式方式来解析XML文档的方式。可以使用QXmlStreamReader类来读取XML文档,并根据读取到的事件来处理XML文档中的内容。
3使用第三方库如TinyXML、PugiXML等。

        如果XML文档很大,DOM树最终可能会保留大量内存,对于这样的文档QXmlStreamReader可能是更好的解决方案。本文并不讨论使用第三方库的情况。

        以下是一个简单的XML文档示例:

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <book category="fiction">
    <title lang="en">Harry Potter</title>
    <author>J.K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="non-fiction">
    <title lang="en">The Great Gatsby</title>
    <author>F. Scott Fitzgerald</author>
    <year>1925</year>
    <price>19.99</price>
  </book>
</bookstore>

        接下来就使用Qt中的两种方式来分别读取和生成这个简单的XML文档。

方式1(使用Qt的内置XML模块)

解析XML文档

void xmltest::readXML_dom(){
    QFile xmlFile("xml路径.xml");

    if(!xmlFile.exists()){
        qDebug()<<"文档不存在:"<<xmlFile.fileName();
                                     return;
    }

    if(!xmlFile.open(QIODevice::ReadOnly)){
        qDebug()<<"文档打开失败:"<<xmlFile.fileName();
            return;
    }

    QString errorStr;
    int errorLine,errorColumn;
    QDomDocument dom;
    bool canSet=dom.setContent(&xmlFile,&errorStr,&errorLine,&errorColumn);
    if(!canSet){
        xmlFile.close();
        qDebug()<<"errorStr:"<<errorStr<<"errorLine:"<<errorLine<<"errorColumn:"<<errorColumn;
        return;
    }
    xmlFile.close();

    QDomElement bookStoreEle=dom.documentElement();
    QString bookStore=bookStoreEle.tagName();
    qDebug()<<bookStore;
    QDomNode bookNode=bookStoreEle.firstChild();
    while(!bookNode.isNull()){
        QDomElement bookEle=bookNode.toElement();
        if(!bookEle.isNull()){
            QString tagName=bookEle.tagName();
            QDomAttr attr=bookEle.attributeNode("category");
            QString attrStr=attr.value();
            qDebug()<<"tagName:"+tagName<<"category:"+attrStr;

            QDomNode bookInfoNode=bookEle.firstChild();
            while(!bookInfoNode.isNull()){
                QString bookNodeName=bookInfoNode.nodeName();
                QString bookNodeContent=bookInfoNode.toElement().text();
                if(bookInfoNode.hasAttributes()){
                    qDebug()<<bookInfoNode.attributes().namedItem("lang").nodeValue();
                }
                qDebug()<<bookNodeName<<bookNodeContent;

                bookInfoNode=bookInfoNode.nextSibling();
            }
        }
        bookNode=bookNode.nextSibling();
    }
}

执行结果: 

"bookstore"
"tagName:book" "category:fiction"
"en"
"title" "Harry Potter"
"author" "J.K. Rowling"
"year" "2005"
"price" "29.99"
"tagName:book" "category:non-fiction"
"en"
"title" "The Great Gatsby"    
"author" "F. Scott Fitzgerald"
"year" "1925"
"price" "19.99"

生成XML文档

void xmltest::writeXML_dom(){
    QDomDocument doc;

    QDomProcessingInstruction xmlDeclaration = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
    doc.appendChild(xmlDeclaration);

    QDomElement bookStoreEle=doc.createElement("bookstore");


    QDomElement bookEle1=doc.createElement("book");
    bookEle1.setAttribute("category","fiction");

    QDomElement titleEle1=doc.createElement("title");
    titleEle1.setAttribute("lang","en");
    QDomText titleText1=doc.createTextNode("Harry Potter");
    titleEle1.appendChild(titleText1);
    QDomElement authorEle1=doc.createElement("author");
    QDomText authorText1=doc.createTextNode("J.K. Rowling");
    authorEle1.appendChild(authorText1);
    QDomElement yearEle1=doc.createElement("year");
    QDomText yearText1=doc.createTextNode("2005");
    yearEle1.appendChild(yearText1);
    QDomElement priceEle1=doc.createElement("price");
    QDomText priceText1=doc.createTextNode("29.99");
    priceEle1.appendChild(priceText1);

    bookEle1.appendChild(titleEle1);
    bookEle1.appendChild(authorEle1);
    bookEle1.appendChild(yearEle1);
    bookEle1.appendChild(priceEle1);

    //QDomElement bookEle2; //这种方式是不行的。
    //bookEle2.setTagName("book");
    //bookStoreEle.appendChild(bookEle2);

    QDomElement bookEle2=doc.createElement("book");
    bookEle2.setAttribute("category","non-fiction");

    QDomElement titleEle2=doc.createElement("title");
    titleEle2.setAttribute("lang","en");
    QDomText titleText2=doc.createTextNode("The Great Gatsby");
    titleEle2.appendChild(titleText2);
    QDomElement authorEle2=doc.createElement("author");
    QDomText authorText2=doc.createTextNode("F. Scott Fitzgerald");
    authorEle2.appendChild(authorText2);
    QDomElement yearEle2=doc.createElement("year");
    QDomText yearText2=doc.createTextNode("1925");
    yearEle2.appendChild(yearText2);
    QDomElement priceEle2=doc.createElement("price");
    QDomText priceText2=doc.createTextNode("19.99");
    priceEle2.appendChild(priceText2);

    bookEle2.appendChild(titleEle2);
    bookEle2.appendChild(authorEle2);
    bookEle2.appendChild(yearEle2);
    bookEle2.appendChild(priceEle2);

    bookStoreEle.appendChild(bookEle1);
    bookStoreEle.appendChild(bookEle2);

    doc.appendChild(bookStoreEle);

    QFile xmlFile("xml路径.xml");
    if(!xmlFile.open(QIODevice::WriteOnly | QIODevice::Text)){
        qDebug() << "打开文件失败.";
        return;
    }
    QTextStream stream(&xmlFile);
    doc.save(stream, 4); // 4 表示缩进的空格数量
    xmlFile.close();
}

         这只是简单的示例,QDomDocument、QDomNode、QDomElement提供了丰富的接口可供使用。

方式2(QXmlStreamReader和QXmlStreamWriter)

解析XML文档

void xmltest::readXML_stream(){
    QFile xmlFile("xml路径.xml");

    if(!xmlFile.exists()){
        qDebug()<<"文档不存在:"<<xmlFile.fileName();
                                     return;
    }

    if(!xmlFile.open(QIODevice::ReadOnly)){
        qDebug()<<"文档打开失败:"<<xmlFile.fileName();
            return;
    }

    QXmlStreamReader xmlReader(&xmlFile);
    while(!xmlReader.atEnd()&&!xmlReader.hasError()){
        QXmlStreamReader::TokenType token=xmlReader.readNext();
        if(token==QXmlStreamReader::StartDocument){
            qDebug() << "Start Document";
        }else if(token==QXmlStreamReader::StartElement){
            qDebug() << "Start Element: " << xmlReader.name().toString();
            // 处理不同的元素
            if (xmlReader.name().toString() == "book") {
                qDebug() << "Category: " << xmlReader.attributes().value("category").toString();
            } else if (xmlReader.name().toString() == "title") {
                qDebug() << "Title: " << xmlReader.readElementText();
            } else if (xmlReader.name().toString() == "author") {
                qDebug() << "Author: " << xmlReader.readElementText();
            } else if (xmlReader.name().toString() == "year") {
                qDebug() << "Year: " << xmlReader.readElementText().toInt();
            } else if (xmlReader.name().toString() == "price") {
                qDebug() << "Price: " << xmlReader.readElementText().toDouble();
            }
        } else if (token == QXmlStreamReader::EndElement) {
            qDebug() << "End Element: " << xmlReader.name().toString();
        }
    }
    if (xmlReader.hasError()) {
        qDebug() << "XML Parsing Error: " << xmlReader.errorString();
    }

    xmlFile.close();
}

        运行结果:

Start Document
Start Element:  "bookstore"
Start Element:  "book"     
Category:  "fiction"       
Start Element:  "title"    
Title:  "Harry Potter"     
Start Element:  "author"   
Author:  "J.K. Rowling"    
Start Element:  "year"        
Year:  2005
Start Element:  "price"       
Price:  29.99
End Element:  "book"
Start Element:  "book"        
Category:  "non-fiction"      
Start Element:  "title"       
Title:  "The Great Gatsby"    
Start Element:  "author"      
Author:  "F. Scott Fitzgerald"
Start Element:  "year"        
Year:  1925
Start Element:  "price"  
Price:  19.99
End Element:  "book"     
End Element:  "bookstore"

生成XML文档

void xmltest::writeXML_stream(){
    QFile file("xml路径.xml");
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file for writing.";
        return;
    }

    QXmlStreamWriter xmlWriter(&file);
    xmlWriter.setAutoFormatting(true);

    xmlWriter.writeStartDocument();
    xmlWriter.writeStartElement("bookstore");

    // 写入第一本书的信息
    xmlWriter.writeStartElement("book");
    xmlWriter.writeAttribute("category", "fiction");

    xmlWriter.writeStartElement("title");
    xmlWriter.writeAttribute("lang", "en");
    xmlWriter.writeCharacters("Harry Potter");
    xmlWriter.writeEndElement(); // title

    xmlWriter.writeStartElement("author");
    xmlWriter.writeCharacters("J.K. Rowling");
    xmlWriter.writeEndElement(); // author

    xmlWriter.writeStartElement("year");
    xmlWriter.writeCharacters("2005");
    xmlWriter.writeEndElement(); // year

    xmlWriter.writeStartElement("price");
    xmlWriter.writeCharacters("29.99");
    xmlWriter.writeEndElement(); // price

    xmlWriter.writeEndElement(); // book

    // 写入第二本书的信息,类似于第一本书
    xmlWriter.writeStartElement("book");
    xmlWriter.writeAttribute("category", "non-fiction");

    xmlWriter.writeStartElement("title");
    xmlWriter.writeAttribute("lang", "en");
    xmlWriter.writeCharacters("The Great Gatsby");
    xmlWriter.writeEndElement(); // title

    xmlWriter.writeStartElement("author");
    xmlWriter.writeCharacters("F. Scott Fitzgerald");
    xmlWriter.writeEndElement(); // author

    xmlWriter.writeStartElement("year");
    xmlWriter.writeCharacters("1925");
    xmlWriter.writeEndElement(); // year

    xmlWriter.writeStartElement("price");
    xmlWriter.writeCharacters("19.99");
    xmlWriter.writeEndElement(); // price

    xmlWriter.writeEndElement(); // book

    xmlWriter.writeEndElement(); // bookstore
    xmlWriter.writeEndDocument();

    file.close();
}

        QXmlStreamReader和QXmlStreamWriter也可以与QDomDocument这些内容相结合。

结语

        以上示例只是简单的使用了Qt解析XML格式的文档,可以通过Qt官方文档来学习对XML更为细致全面的操作。另外,在Qt5中有QXmlQuery类来支持XPath查询XML文档的内容,Qt6中已经不支持。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt中,可以使用QXmlStreamReader和QXmlStreamWriter类来解析和生成XML文档。 QXmlStreamReader类提供了一种逐步读取XML文档的方式。您可以使用它来遍历XML文档中的元素、属性和文本节点,并从中获取信息。以下是一个使用QXmlStreamReader类解析XML文档的示例: ```cpp QFile file("example.xml"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QXmlStreamReader reader(&file); while (!reader.atEnd()) { reader.readNext(); if (reader.isStartElement()) { if (reader.name() == "person") { QString name = reader.attributes().value("name").toString(); qDebug() << "Name:" << name; } } } file.close(); ``` 在上面的示例中,我们打开名为“example.xml”的文件并创建一个QXmlStreamReader对象。然后,我们使用一个循环来遍历XML文档中的所有元素。如果遇到一个起始元素,我们检查它是否是一个名为“person”的元素。如果是,我们获取其“name”属性的值并将其打印出来。 QXmlStreamWriter类提供了一种生成XML文档的方式。您可以使用它来创建元素、属性和文本节点,并将它们写入XML文档中。以下是一个使用QXmlStreamWriter类生成XML文档的示例: ```cpp QFile file("example.xml"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; QXmlStreamWriter writer(&file); writer.setAutoFormatting(true); writer.writeStartDocument(); writer.writeStartElement("root"); writer.writeStartElement("person"); writer.writeAttribute("name", "Alice"); writer.writeTextElement("age", "25"); writer.writeEndElement(); writer.writeStartElement("person"); writer.writeAttribute("name", "Bob"); writer.writeTextElement("age", "30"); writer.writeEndElement(); writer.writeEndElement(); writer.writeEndDocument(); file.close(); ``` 在上面的示例中,我们打开名为“example.xml”的文件并创建一个QXmlStreamWriter对象。然后,我们使用它来生成XML文档。我们首先调用writeStartDocument()方法来写入XML文档的头部信息。然后,我们使用writeStartElement()和writeEndElement()方法来创建根元素和子元素。我们还使用writeAttribute()和writeTextElement()方法来添加属性和文本节点。最后,我们调用writeEndDocument()方法来完成XML文档的写入。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值