• QDomDocument 读取和编辑xml文件


    Qt中几种操作xml的方式

    • 流方式
    • sax方式
    • dom方式

    初学时,我常常采用流方式读取xml,该方式简单直观,容易理解。之后遇到了需要修改xml并重新写回的情况,流方式就显得捉襟见肘了。

    sax方式接触不多,从来没有在实际生产中使用过。

    dom方式概念复杂,对于个人来说,文档也不是很清晰,导致我一直对这个方式不甚了解,最近下定决心好好研究一番,也算是大致清楚了个中“套路”,在此记录,以便今后查阅。

    注意:如果你对QDomDocument没有任何了解,则不适合阅读此文章。如果你在使用QDomDocumentde的过程中产生了疑惑,则此文可能对你产生帮助。

    如有疏漏,还望指正。

    QDomNode ? QDomElemet? QDomAttr?QDomText?

    初见QDomDocument时,我被这些东西搞得一头雾水。
    直到我看到了某博客中这样一段话:

    QDom前缀的都是代表节点类型。所以有,QDomElement代表一个Element节点,而QDomText代表一个Text节点。QDomNode类可以存储任意类型的节点。如果想进一步处理一个节点,首先必须把它转化为正确的数据类型。QDomNode调用toElement()以把它转化成QDomElement,然后调用tagName()来获得元素的标签名称。如果节点不是Element类型,那么toElement()函数就返回一个空QDomElement对象和一个空标签。1

    我们对xml操作,无非对节点文本,节点属性进行操作,因此,我着重在这个基础上整理一下。

    QDomNode 兼容所有节点类型。
    这里只讨论QDomNode为QDomElemet的情况;此时读者心里一惊,难道,还有不是的情况?当然有!

    QDomNode QDomElemet

    举个简单例子
    你看!

    • 有如下xml
    <bookstore category="xml">
        <book category="CHILDREN">
          <title>Harry Potter</title>
          <author>J K. Rowling</author>
          <year>2005</year>
          <price>29.99</price>
        </book>
        <!-- asdasd-->
        <book category="WEB">
          <title>Learning XML</title>
          <author>Erik T. Ray</author>
          <year>2003</year>
          <price>39.95</price>
        </book>
        <test>hello</test>
    </bookstore>

    有如下代码:

    • code 01
        QDomElement root = doc.documentElement();
    
        QDomNode node=  root.firstChild();
        qDebug() << root.attributeNode("category").value();
        while(!node.isNull())
        {
           qDebug() << "xx";
           node = node.nextSibling();
        }

    结果会输出几个xx呢?

    代码做出如下更改

    • code 02
        QDomElement root = doc.documentElement();
    
        QDomElement node=  root.firstChildElement();
        qDebug() << root.attributeNode("category").value();
        while(!node.isNull())
        {
           qDebug() << "xx";
           node = node.nextSiblingElement();
        }

    结果会输出几个xx呢?

    答案分别是4和3!:smirk: :smirk:

    结论:注释QDomNode而不是QDomElement

    到这里,大家应该就能明白两者的区别了。也应该能读懂上边的

    QDomNode调用toElement()以把它转化成QDomElement,然后调用tagName()来获得元素的标签名称。如果节点不是Element类型,那么toElement()函数就返回一个空QDomElement对象和一个空标签

    [========]

    QDomElemet 与 QDomAttr QDomText

    经过上面的试验,我们还可以得到另一个结论,那就是
    属性不是QDomELement子QDomELement
    属性不是QDomNode子QDomNode

    还有一件事我们不知道,那就是QDomELement中的文本算是它的子QDomELement么?

    <bookstore category="xml">hello</bookstore>
    • code 03
        QDomElement ele=  root.firstChildElement();
    
        while(!ele.isNull())
        {
           qDebug() << "xx";
           ele = ele.nextSiblingElement();
        }

    程序不会有任何输出
    文本不是QDomELement子QDomELement

    • code 04
        QDomNode node=  root.firstChild();
    
        while(!node.isNull())
        {
           qDebug() << "xx";
           node = node.nextSibling();
        }

    程序将会输出一个xx
    文本QDomNode子QDomNode

    了解了它们之间的联系之后,我们现在迫切的需要知道一个问题,既然文本和属性都不是子QDomELement,如何获取到文本和属性呢?

    读写xml

    遍历某QDomELement的 子QDomELement

    • 示例xml
    <bookstore category="xml">
        <book category="CHILDREN">
          <title>Harry Potter</title>
          <author>J K. Rowling</author>
          <year>2005</year>
          <price>29.99</price>
        </book>
        <book category="WEB">
          <title>Learning XML</title>
          <author>Erik T. Ray</author>
          <year>2003</year>
          <price>39.95</price>
        </book>
        <test>hello</test>
    </bookstore>
    • code 05 遍历
        QDomDocument doc = QDomDocument();
        QFile file("./test.xml");
        file.open(QFile::ReadWrite);
        doc.setContent(&file);
    
        QDomElement root = doc.documentElement();
    
        QDomElement ele=  root.firstChildElement();
    
        while(!ele.isNull())
        {
           //do something
    
           ele = ele.nextSiblingElement();
        }

    doc.documentElement()获取最顶级的QDomDocument,接下来的循环遍历了它所有的QDomDocument,对于它的子QDomDocument,同样可以使用以上方法。
    如果一个QDomDocumentfirstChildElement()返回的QDomElement为空(ele.isNull() 为 true),则说明他没有子QDomElement,也就意味着他是xml的最底层了,接下来介绍获取文本和属性的方法。

    • code 06 读取
        QDomDocument doc = QDomDocument();
        QFile file("./test.xml");
        file.open(QFile::ReadWrite);
        doc.setContent(&file);
    
        QDomElement root = doc.documentElement();
    
        QDomElement ele=  root.firstChildElement();
    
        qDebug() << root.attributeNode("category").nodeValue();
    
        while(!ele.isNull())
        {
            //此处可以有多种判定方法,此处只是采用了子元素为空判定
            //实际生产中你很可能不需要这样判断,根据xml结构直接判定元素名称即可
            //如 if(ele.tagName() == "xxxx")
            if(ele.firstChildElement().isNull())
            {
                qDebug() << ele.tagName();
                qDebug() << ele.text();
    
                //文本是ele的子QDomNode,而不是ele本身! 所以这样不会输出任何东西!
                qDebug() << ele.toText().nodeValue();
                //如果真的需要转化为QDomText
                QDomNode node = ele.firstChild();
                while (!node.isNull()) {
                    if(node.isText())
                    {
                        qDebug() << node.toText().nodeValue();
                    }
                    node = node.nextSibling();
                }
    
            }
           ele = ele.nextSiblingElement();
        }

    输出

    "xml"
    "test"
    "hello"
    ""
    "hello"

    修改很简单,只需要将上边的nodeValue函数改为setNodeValue即可。记得要写回文件改动才会生效哦(详情请查看save方法的帮助文档)。

    除此之外QDomDocument还提供了替换节点的方法,自行探索。

    转载请注明出处

    <wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">





  • 相关阅读:
    华硕路由器5g/2.4g信道合并
    反冲(倒冲)
    成本中心与利润中心
    IFRS
    word首行大写关闭
    电子笔记还是手写笔记
    SAP程序跟踪
    Python银行机器学习:回归、随机森林、KNN近邻、决策树、高斯朴素贝叶斯、支持向量机svm分析营销活动数据
    R语言结构方程模型SEM分析心理学和营销研究数据路径图可视化
    拓端tecdat|Python信贷风控模型:梯度提升Adaboost,XGBoost,SGD, GBOOST, SVC,随机森林, KNN预测金融信贷违约支付和模型优化
  • 原文地址:https://www.cnblogs.com/xdblog/p/11143022.html
Copyright © 2020-2023  润新知