初学时,我经常采用流方式读取xml,该方式简单直观,容易理解。以后遇到了须要修改xml并从新写回的状况,流方式就显得捉襟见肘了。html
sax方式接触很少,历来没有在实际生产中使用过。node
dom方式概念复杂,对于我的来讲,文档也不是很清晰,致使我一直对这个方式不甚了解,最近下定决心好好研究一番,也算是大体清楚了个中“套路”,在此记录,以便从此查阅。dom
注意:若是你对QDomDocument没有任何了解,则不适合阅读此文章。若是你在使用QDomDocumentde的过程当中产生了疑惑,则此文可能对你产生帮助。函数
若有疏漏,还望指正。code
初见QDomDocument时,我被这些东西搞得一头雾水。
直到我看到了某博客中这样一段话:xml
QDom前缀的都是表明节点类型。因此有,QDomElement表明一个Element节点,而QDomText表明一个Text节点。QDomNode类能够存储任意类型的节点。若是想进一步处理一个节点,首先必须把它转化为正确的数据类型。QDomNode调用toElement()以把它转化成QDomElement,而后调用tagName()来得到元素的标签名称。若是节点不是Element类型,那么toElement()函数就返回一个空QDomElement对象和一个空标签。1htm
咱们对xml操做,无非对节点文本,节点属性进行操做,所以,我着重在这个基础上整理一下。对象
QDomNode 兼容全部节点类型。
这里只讨论QDomNode为QDomElemet的状况;此时读者内心一惊,难道,还有不是的状况?固然有!blog
举个简单例子
你看!文档
<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>
有以下代码:
QDomElement root = doc.documentElement(); QDomNode node= root.firstChild(); qDebug() << root.attributeNode("category").value(); while(!node.isNull()) { qDebug() << "xx"; node = node.nextSibling(); }
结果会输出几个xx呢?
代码作出以下更改
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对象和一个空标签
[========]
通过上面的试验,咱们还能够获得另外一个结论,那就是
属性
不是QDomELement
的子QDomELement
属性
不是QDomNode
的子QDomNode
还有一件事咱们不知道,那就是QDomELement
中的文本算是它的子QDomELement
么?
<bookstore category="xml">hello</bookstore>
QDomElement ele= root.firstChildElement(); while(!ele.isNull()) { qDebug() << "xx"; ele = ele.nextSiblingElement(); }
程序不会有任何输出
文本
不是QDomELement
的子QDomELement
QDomNode node= root.firstChild(); while(!node.isNull()) { qDebug() << "xx"; node = node.nextSibling(); }
程序将会输出一个xx
文本
是QDomNode
的子QDomNode
了解了它们之间的联系以后,咱们如今迫切的须要知道一个问题,既然文本和属性都不是子QDomELement,如何获取到文本和属性呢?
<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>
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的最底层了,接下来介绍获取文本和属性的方法。
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还提供了替换节点的方法,自行探索。
转载请注明出处