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;">

 
 
 
 

QDomDocument 读取和编辑xml文件的更多相关文章

  1. python 编辑文件时路径问题解决方法:文件或者目录不存在、文件编辑后无法保存等(以编辑xml文件为例)

    1.获取工程所在根路径:根路径=os.path.dirname(os.path.abspath('__file__')) 2.将获取的根路径和相对路径组合:组合路径=os.path.join(根路径, ...

  2. Eclipse编辑XML文件的代码提示

    1.Eclipse无法解析的情形 Eclipse中编辑XML文件时,能够代码自动提示,是因为在XML头部引入了DTD文件(文档类型定义),Eclipse就是通过解析这个DTD文件,来达到代码提示的功能 ...

  3. 编辑xml文件时不能自动提示问题的解决

    在编辑xml文件时,eclipse总是不能自动提示,在网上找了一些资料,大部分都是说关于xml editor配置的,下面也把这个方法罗列在下面,以供参考: 解决办法:在eclipse的菜单里,找到wi ...

  4. opencv局限:cv::FileStorage读取中,xml文件的第一层节点不能超过4个

    今天测试发现一个问题,cv::FileStorage读取中,xml文件的第一层节点不能超过4个. <?xml version="1.0"?> <opencv_st ...

  5. 未联网下,在eclipse中编辑xml文件如何自动提示设置

    断网情况下,用eclipse编辑xml文件如何自动提示? 以编辑hibernate中的xml为例: 首先,我们都知道xml提示是引用.dtd文件的. 1.复制这个dtd路径,设置eclipse属性,搜 ...

  6. TinyXML2读取和创建XML文件 分类: C/C++ 2015-03-14 13:29 94人阅读 评论(0) 收藏

    TinyXML2是simple.small.efficient C++ XML文件解析库!方便易于使用,是对TinyXML的升级改写!源码见本人上传到CSDN的TinyXML2.rar资源:http: ...

  7. 解决Eclipse中编辑xml文件的智能提示问题,最简单的是第二种方法。

    Eclipse for Android xml 文件代码自动提示功能,介绍Eclipse 编辑器中实现xml 文件代码自动智能提示功能,解决eclipse 代码提示失效.eclipse 不能自动提示. ...

  8. C#读取和写入XML文件

    关于xml是属于一个比较重要的东西,在平时开发的过程中,这块内容最主要的是要掌握XML内容的读取和写入操作. 一.什么是XML? XML 指可扩展标记语言(EXtensible Markup Lang ...

  9. [转]解决Eclipse中编辑xml文件的智能提示问题

    转自:http://hi.baidu.com/cghroom/item/48fd2d0dc1fc23c675cd3c3e 摘要:  Eclipse for Android xml 文件代码自动提示功能 ...

随机推荐

  1. WPF 实现波浪浮动效果

    原文:WPF 实现波浪浮动效果 目标:实现界面图标Load时,整体图标出现上下波浪浮动效果,如下图: 前台代码: <Windowxmlns="http://schemas.micros ...

  2. WPF获取读取电脑指定文件夹中的指定文件的地址

    //保存指定文件夹中的指定文件的地址 string List<string> mListUri = new List<string>(); //文件夹地址 string fol ...

  3. C#操作EXCEL常见操作集合(行高,列宽,合并单元格,单元格边框线)

    private _Workbook _workBook = null; private Worksheet _workSheet = null; private Excel.Application _ ...

  4. (015)实现一个函数来检查是否平衡树(keep it up)

    实现一个函数来检查是否平衡树.这个问题而言. 平衡指的是这棵树随意两个叶子结点到根结点的距离之差不大于1. 这个题我们能够採用暴力搜索,找到叶子节点到根节点的最小值和最大值.然后他们的差假设大于1就不 ...

  5. Gtk+/Gtkmm介绍与安装(有继承关系图)

    GTK+是一套跨平台的,以C语言编写的GUI类库,它起源于GNU的图像处理程序"GIMP",因而被起名为"The GIMP Toolkit",从一开始它就被设计 ...

  6. StaticResource和DynamicResource

    Resource 资源(Resource)是保存在可执行文件中的一种不可执行数据,用来保存一些可以被重复利用的样式,对象定义以及一些传统的资源如二进制数据,图片等等我们可以在任何元素上定义资源 Sta ...

  7. WPF应用无法使用Snoop分析的解决办法

    如果WPF程序是以管理员身份启动的,Snoop不是用管理员身份启动,那就不行. 用管理员身份启动snoop,就可以了. 管理员身份启动cmd,然后启动snoop,ok.

  8. swagger-editor

    前言 上一篇文章我们有提到Swagger做接口的定义是采用yaml语言的,当然,yaml是个啥,大家自行百度.阿福在此不做赘述了.但是,今天我们要来讲的是yaml支持比较好的Swagger-Edito ...

  9. aspx页面@Page指令解析

    @Page指令位于每个ASP.NET页面的顶部,告诉ASP.NET这个具体页面使用什么属性,以及该页面继承的用户控件.ASP.NET页面@Page指令属性有:AspCompat.Async.Async ...

  10. ArcGIS for Desktop入门教程_第七章_使用ArcGIS进行空间分析 - ArcGIS知乎-新一代ArcGIS问答社区

    原文:ArcGIS for Desktop入门教程_第七章_使用ArcGIS进行空间分析 - ArcGIS知乎-新一代ArcGIS问答社区 1 使用ArcGIS进行空间分析 1.1 GIS分析基础 G ...