zoukankan      html  css  js  c++  java
  • Qt XML读取写入操作

     

    XML(eXtensible Markup Language,可扩展标记语言)是普通用于数据交换和数据存储的一种多用途文本文件格式;

    SVG(可标量矢量图形)XML格式,QtSvg模块提供了可用于载入并呈现SVG图像的类;

    MathML(数学标记语言)XML格式的绘制文档,可以使用Qt Solution中的QtMmlWidget操作;

    对于一般的XML数据处理,Qt提供了QtXml模块,QtXml提供了三种不同的应用程序接口来读取XML文档:

    1、QXmlStreamReader

         用于读取格式良好的XML文档的快速解析器,该类最快且最易于使用,并提供了与其他Qt兼容的应用程序编程接口,很适用于编写单通道解析器;

         下图是QXmlStreamReader的记号:

          

       如下XML文档:

             <body>

                     <quoto>My test XML</quoto>

            </body>

    QXmlStreamReader解析这个文档,readNext()每次读取一个元素都会生成一个新记号,用getter函数可以读取更多信息:

           遍历整个文档会有如下输出:

         StartDocument

        StartElement(name()=="body")

           StartElement(name()=="quoto")

       Characters(text()=="My test XML")

       EndElement(name()=="quoto")

       EndElement(name()=="body")

    QXmlStreamReader读取如下的XML文件

    <?xml version="1.0"?>
    <bookindex>
        <entry term="sidebearings">
            <page>10</page>
            <page>34-35</page>
            <page>307-308</page>
        </entry>
        <entry term="subtraction">
            <entry term="of pictures">
                <page>115</page>
                <page>244</page>
            </entry>
            <entry term="of vectors">
                <page>9</page>
            </entry>
        </entry>
    </bookindex>


    通常是按层遍历方式,下面来从代码体验一下:

    XmlStreamReader::XmlStreamReader(QTreeWidget*tree)

    {
        treeWidget = tree;
    }
    bool XmlStreamReader::readFile(const QString &fileName)
    {
        QFile file(fileName);
        if (!file.open(QFile::ReadOnly | QFile::Text)) {
            std::cerr << "Error: Cannot read file " << qPrintable(fileName)
                      << ": " << qPrintable(file.errorString())
                      << std::endl;
            return false;
        }
        qDebug()<<QString("read success");
        reader.setDevice(&file);
        reader.readNext();
        while (!reader.atEnd()) {
            if (reader.isStartElement()) {
                if (reader.name() == "bookindex") {
                    readBookindexElement();
                } else {
                    reader.raiseError(QObject::tr("Not a bookindex file"));
                }
            } else {
                reader.readNext();
            }
        }
        file.close();
        if (reader.hasError()) {
            std::cerr << "Error: Failed to parse file "
                      << qPrintable(fileName) << ": "
                      << qPrintable(reader.errorString()) << std::endl;
            return false;
        } else if (file.error() != QFile::NoError) {
            std::cerr << "Error: Cannot read file " << qPrintable(fileName)
                      << ": " << qPrintable(file.errorString())
                      << std::endl;
            return false;
        }
        return true;
    }
    void XmlStreamReader::readBookindexElement()
    {
        reader.readNext();
        while (!reader.atEnd()) {
            if (reader.isEndElement()) {
                reader.readNext();
                break;
            }
            if (reader.isStartElement()) {
                if (reader.name() == "entry") {
                    readEntryElement(treeWidget->invisibleRootItem());
                } else {
                    skipUnknownElement();
                }
            } else {
                reader.readNext();
            }
        }
    }
    void XmlStreamReader::readEntryElement(QTreeWidgetItem *parent)
    {
        QTreeWidgetItem *item = new QTreeWidgetItem(parent);
        item->setText(0, reader.attributes().value("term").toString());
        reader.readNext();
        while (!reader.atEnd()) {
            if (reader.isEndElement()) {
                reader.readNext();
                break;
            }
            if (reader.isStartElement()) {
                if (reader.name() == "entry") {
                    readEntryElement(item);
                } else if (reader.name() == "page") {
                    readPageElement(item);
                } else {
                    skipUnknownElement();
                }
            } else {
                reader.readNext();
            }
        }
    }
    void XmlStreamReader::readPageElement(QTreeWidgetItem *parent)
    {
        QString page = reader.readElementText();
        if (reader.isEndElement())
            reader.readNext();
        QString allPages = parent->text(1);
        if (!allPages.isEmpty())
            allPages += ", ";
        allPages += page;
        parent->setText(1, allPages);
    }
    void XmlStreamReader::skipUnknownElement()
    {
        reader.readNext();
        while (!reader.atEnd()) {
            if (reader.isEndElement()) {
                reader.readNext();
                break;
            }
            if (reader.isStartElement()) {
                skipUnknownElement();
            } else {
                reader.readNext();
            }
        }
    }

    2、DOM(文档对象模型)

       把XML文档转换为应用程序可以遍历的树形结构,主要优点是它能以任意顺序遍历XML文档的树形表示,同时可以用于多通道解析算法;

          有一些应用程序甚至使用DOM树作为它们的基本数据结构。

           Qt提供了一套用于读取/操作和编写XML文件的非验证型二级DOM实现——这里没有明白非验证型二级的概念,,,,

         下图为DOM节点间的父子关系图:

    Qt中Dom的处理函数,一般只是在函数名前加QDom,常用的 QDomNode, QDomDocument, QDomElement and QDomText.这里不做详细说明,

    下面介绍下简单操作,

    1、首先定义QDomDocument对象,来读取XML文档,

            QDomDocumentdoc;

        if (!doc.setContent(&file, false, &errorStr, &errorLine,
                            &errorColumn)) {
            std::cerr << "Error: Parse error at line " << errorLine << ", "
                      << "column " << errorColumn << ": "
                      << qPrintable(errorStr) << std::endl;
            return false;
        }
    2、QDomElement 来处理XML的元素,这个很重要,该类包含了对子节点的处理,插入删除、以及遍历都会用到它
        QDomElement root = doc.documentElement();
        if (root.tagName() != "bookindex") {
            std::cerr << "Error: Not a bookindex file" << std::endl;
            return false;
        }
    
    
    

    DOM读写XML的方式是一致的,都需要递归向下遍历,这里给出DOM写(或者说修改)XML的代码(http://blog.csdn.net/qustdjx/article/details/7518200):

    #include<QDomDocument>

    QDomDocumentm_doc;//在头文件中声明

    bool DomParser::changeSave()  //

    {
        if(!openXmlFile("/home/qust/qt/XML/2.xml"))
            {
                return false;
            }
            //修改保存xml
        QDomElement root = m_doc.documentElement();
           if(root.tagName()!= "kdevelop")
               return false;
           QDomNode n = root.firstChild();
           while ( !n.isNull() )
           {
               QDomElement e = n.toElement();
               if( !e.isNull())
               {
                           if( e.nodeName() == "general" )
                           {
                               QDomNodeList list = e.childNodes(); //获得元素e的所有子节点的列表
                               for(int a=0; a<list.count(); a++) //遍历该列表
                               {
                                     node = list.at(a);
                                   if(node.isElement())
                                   {
                                       if( node.nodeName() == "author" )
                                       { QDomNode oldnode = node.firstChild();     //标签之间的内容作为节点的子节点出现,得到原来的子节点
                                           node.firstChild().setNodeValue("csdn");   //用提供的value值来设置子节点的内容
    //从这里可以看出,该方法读写通用,QString text=node.firstChild().nodeValue();就可以读取该节点的内容
    
                                           QDomNode newnode = node.firstChild();     //值修改过后
                                           node.replaceChild(newnode,oldnode);      //调用节点的replaceChild方法实现修改功能
                                       }
                                       if( node.nodeName() == "email" )
                                       {
                                           QDomNode oldnode = node.firstChild();
                                           node.firstChild().setNodeValue("test@tom.com");
                                           QDomNode newnode = node.firstChild();
                                           node.replaceChild(newnode,oldnode);
                                       }
                                   }
                               }
                           }
                       }
               n = n.nextSibling();
                 }
                 QFile filexml("/home/qust/qt/XML/2.xml");
                 if( !filexml.open( QFile::WriteOnly | QFile::Truncate) ){
                     qWarning("error::ParserXML->writeOperateXml->file.open
    ");
                     return false;
                        }
                        QTextStream ts(&filexml);
                        ts.reset();
                        ts.setCodec("utf-8");
                        m_doc.save(ts, 4, QDomNode::EncodingFromTextStream);
                        filexml.close();
                        return true;
    }

    3、SAX(XML简单应用程序编程接口)通过虚拟函数直接向应用程序报告"解析事件",这里没有做具体说明,用到再做总结。

  • 相关阅读:
    子矩阵
    [Ahoi2008]Meet 紧急集合
    立体图
    CF933B A Determined Cleanup
    CF746G New Roads
    树的重量
    CF519E A and B and Lecture Rooms
    矩阵
    深入浅出乘法逆元
    20180519模拟赛T2——pretty
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/4087688.html
Copyright © 2011-2022 走看看