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
,同样可以使用以上方法。
如果一个qdomdocument
的firstchildelement()
返回的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;">
上一篇: ZOJ 3408 Gao