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简单应用程序编程接口)通过虚拟函数直接向应用程序报告"解析事件",这里没有做具体说明,用到再做总结。

  • 相关阅读:
    jvm基本结构和解析
    多态的意思
    java中对象的简单解读
    double类型和int类型的区别
    python 解析xml文件
    win10不能映射Ubuntu共享文件
    Qt程序打包
    Ubuntu boot分区文件误删,系统无法启动,怎么解
    ubuntu Boot空间不够问题“The volume boot has only 5.1MB disk space remaining”
    Ubuntu 分辨率更改 xrandr Failed to get size of gamma for output default
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/4087688.html
Copyright © 2011-2022 走看看