Qt中xml的读写

前端之家收集整理的这篇文章主要介绍了Qt中xml的读写前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我们可以看到,如果所要读取的XML文件不是很大,采用DOM读取方法还是很便捷的,由于我用的也是DOM树读取的方法,所以,本文所介绍的也主要是基于DOM的方法读取。
(来自http://blog.sina.com.cn/s/blog_4ac0a0d30100mr53.html)
@H_301_4@

根据常用的操作,我简单的把对XML的操作分为以下几类:@H_301_4@

1 首先对XML文件进行操作,打开文件。@H_301_4@

这个其实就是对文件进行操作,可以把它直接定义为构造函数,在对对象进行初始化时完成。@H_301_4@

TopoDataReader::TopoDataReader(const wstring &filePath):_filePath(filePath),_qDomDoc("mydocument"),_qFile(QString::fromStdWString(filePath))
{
if (!_qFile.open(QIODevice::ReadOnly))
{
return;
}@H_301_4@

if (!_qDomDoc.setContent(&_qFile))
{
_qFile.close();
return;
}
}@H_301_4@

2 读取XML文件中的节点内容@H_301_4@

假设XML文件格式如下@H_301_4@

(1)@H_301_4@

<switchs>@H_301_4@

<switch snmpip=211.87.235.136 newwork=front>@H_301_4@

</switch>@H_301_4@

</switchs>@H_301_4@

(2)@H_301_4@

<ip>211.87.235.136</ip>@H_301_4@

对于第一种情况,采用如下方法:@H_301_4@

QDomElement docElem = _qDomDoc.documentElement();@H_301_4@

QDomNode nodeswitch=docElem.elementsByTagName("switch ");//红色的为标签名@H_301_4@

QDomElement elemnodeswitch=nodeswitch.toElement();@H_301_4@

string snmpip=qPrintable(elemnodeswitch.attribute("snmpip"));//network的也是如此方法获取@H_301_4@

对于第二种情况,采用如下方法:@H_301_4@

直接调用text() API就可以了@H_301_4@

string ip=qPrintable(elementnodeip.text());@H_301_4@

但是,假设文件中有多个同样的节点,如下@H_301_4@

<a>@H_301_4@

<b></b>@H_301_4@

</a>@H_301_4@

这样用elementsByTagName("b")返回的就是一个childNodes()而不是一个单独的node了。@H_301_4@

我们可以使用at()方法具体定位。@H_301_4@

另外,我们还可以使用这样一种方法获取节点的值,假设XML文件如下@H_301_4@

- +<switch snmpIp="192.168.120.251" network="front">
<name>前端主交换机</name>
<description />
- <ipList>
<ip>192.168.120.251</ip>
</ipList>
<rwCommunity>public@120</rwCommunity>
<workMode>true</workMode>
<workStatus>true</workStatus>
<enableAlarm>true</enableAlarm>
<snmpCount>0</snmpCount>
<memoryUtilizationRatio>50.0</memoryUtilizationRatio>
<cpuUtilizationRatio>50.0</cpuUtilizationRatio>
<port>161</port>
<snmpStatus>true</snmpStatus>
<privateName>CZ-5_FA</privateName>
<switchIndex>topLeft</switchIndex>
</switch>
我们可以先获取switch节点,然后得到其childNodes(),于是就可以使用at()方法获取下面的每个节点了(注:从0开始)@H_301_4@

比如说,上面的那个ip节点就是nodeswitch.childNodes().at(3)。@H_301_4@

这样做得好处就是不用担心重复的问题,只要你确定switch节点确定对了,底下的也就一定能确定了。@H_301_4@

3 返回某个节点下子节点的个数@H_301_4@

这个简单,也是直接调API@H_301_4@

QDomElement docElem = _qDomDoc.documentElement();
QDomNode nodetagname=docElem.elementsByTagName(tagname).at(0);//假设有多个tagname此处选第一个
int num=nodetagname.childNodes().size();@H_301_4@

好了,临时想起来就这么多。以后想起来再添。@H_301_4@

@H_301_4@

//============================================================================================================================@H_301_4@

Qt学习之XML读写操作小结
2010年05月25日 评论(0)|浏览(315)点击查看原文@H_301_4@

Qt学习之XML读写操作小结@H_301_4@


在“QQ便签”项目组中我负责有关后台XML操作的实现部分,现在对在项目中用到的XML的相关操作进行简单的小结。@H_301_4@

这几天搜集qt对XML格式文件的读写,着重于DOM这种方式,先将搜集的资料粘贴在下面, 以一个完整的流程:
=======如下:============@H_301_4@


我们知道对XML的操作有两种方法,即DOM方式和SAX方式。二者主要区别是:DOM实现方式操作非常简单,但不适合处理过大文件;而SAX实现方式是能处理很大的XML文件,但是需要开发者写@H_301_4@

一些复杂的代码。Qt提供了对应于这两种用于读取、操作和编写XML的实现类,分别是QDomDocument类和QXmlStreamReader类,由于在项目中涉及的文件不大,因此我们选用QDomDocument类来@H_301_4@

处理。@H_301_4@

项目中涉及便签的增删改查,对应于XML文件中相应标记的读、写和修改,下面分别介绍:@H_301_4@


1. 创建节点,将其写入XML文件,主要操作包括
QDomDocument doc;@H_301_4@

1).创建根节点:QDomElement root = doc.documentElement("rootName " );@H_301_4@

2).创建元素节点:QDomElement element = doc.createElement_x_x("nodeName");@H_301_4@

3).添加元素节点到根节点:root. appendChild(element);@H_301_4@

4).创建元素文本:QDomText nodeText=doc.createTextNode("text");@H_301_4@

5).添加元素文本到元素节点:element. appendChild(nodeText);@H_301_4@

在本项目中,假设便签的属性有序号、名字、内容、字体、字号、颜色、粗细、斜体、下划线这几项,则在文件添加一个便签节点的操作如下:@H_301_4@

QDomDocument doc;@H_301_4@

instruction = doc.createProcessingInstruction("xml","version="1.0" encoding="UTF-8"");@H_301_4@

doc.appendChild(instruction);@H_301_4@

QDomElement root = doc.createElement_x_x("Notes");@H_301_4@

doc.appendChild(root);@H_301_4@

QDomElement note = doc.createElement_x_x("note");@H_301_4@

root.appendChild(note);@H_301_4@

QDomElement no = doc.createElement_x_x("no");@H_301_4@

note.appendChild(no);@H_301_4@

...@H_301_4@

QDomText no_text = doc.createTextNode("001");@H_301_4@

则得到一个便签节点,将其保存到test.xml文件中,代码如下:@H_301_4@

QFile file("test.xml");@H_301_4@

if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate |QIODevice::Text))@H_301_4@

return ;@H_301_4@

QTextStream out(&file);@H_301_4@

out.setCodec("UTF-8");@H_301_4@

doc.save(out,4,QDomNode::EncodingFromTextStream);@H_301_4@

file.close();@H_301_4@

则test.xml文件:@H_301_4@

<?xml version="1.0" encoding="UTF-8"?>@H_301_4@

<Notes>@H_301_4@

<note>@H_301_4@

<no>001</no>@H_301_4@

<name>2010-05-10(13:53:24)</name>@H_301_4@

<content>A meeting!</content>@H_301_4@

<font>Script MT Bold</font>@H_301_4@

<fontSize>16</fontSize>@H_301_4@

<color> #00ffff</color>@H_301_4@

<weight>0</weight>@H_301_4@

<fontItalic>true</fontItalic>@H_301_4@

<fontUnderline>true</fontUnderline>@H_301_4@

</note>@H_301_4@

</Notes>@H_301_4@

上面是创建一个便签节点,若要继续添加便签节点,则需要在已有节点后增加一个新节点,并重写入XML文件。@H_301_4@

2. 加载、查找便签时要读取XML文档中的节点信息,DOM实现方式是将整个文档当作一个对象来装入内存进行处理,然后开发者可以访问这个对象中的每一个节点,每一个节点对应XML文件里@H_301_4@

的一个标记。@H_301_4@

主要操作包括:@H_301_4@

1).读取根节点:QDomElement root = doc.documentElement();@H_301_4@

2).读取第一个子节点:QDomNode node = root.firstChild();@H_301_4@

3).读取下一个子节点:node = node.nextSibling();@H_301_4@

4).匹配结点标记:node.toElement().tagName() == "note"@H_301_4@

5).读取节点文本:no = childNode.toText().data();
//========================遍历节点================
可以通过doc.childNodes()获得doc的所有的子节点列表QDomNodeList。比如@H_301_4@

QDomNodeList list=doc.childNodes();@H_301_4@

for(int i=0;i<list.count();i++){@H_301_4@

QDomNode node=list.at(i);//好的风格当然是把定义写在外面:(@H_301_4@

//qDebug()<<”node name is “<<node.nodeName();@H_301_4@

//qDebug()<<”node type is “<<.nodeType();@H_301_4@

}
//==============================================@H_301_4@

以下是项目中读取便签属性函数实现代码:@H_301_4@

void MainWindow::parseAttr(const QDomElement &element)@H_301_4@

{@H_301_4@

QString no,name,content,font,fontSize,color;@H_301_4@

QDomNode node = element.firstChild();@H_301_4@

while (!node.isNull()) {@H_301_4@

if (node.toElement().tagName() == "note") {//匹配note节点@H_301_4@

parseAttr(node.toElement());@H_301_4@

} else if (node.toElement().tagName() == "no") {//匹配属性no@H_301_4@

QDomNode childNode = node.firstChild();@H_301_4@

if (childNode.nodeType() == QDomNode::TextNode) {@H_301_4@

no = childNode.toText().data();@H_301_4@

}@H_301_4@

else if (node.toElement().tagName() == "name") //匹配属性name@H_301_4@

node = node.nextSibling();//读取兄弟节点@H_301_4@

3. 删除便签时,要删除相应的XML节点,用到的主要函数为:root.removeChild(node); 但在删除某个节点后要重写整个文件。@H_301_4@

以上对XML文件的重写操作是必须的,因此在文件的打开方式中要加上QIODevice::Truncate,表示覆盖重写。目前还没有找到可以直接修改文件方法,但若文件很大的情况下,必须考虑相@H_301_4@

应的效率问题。@H_301_4@

由于本项目在启动时需要将所有便签加载到内存,因此选用DOM方式比较合适,但如果处理的XML文件很大,而且不需要全部读到内存时,可以用SAX实现方式,它按阶段将文档读取到内存中,@H_301_4@

在碰到标签或者其它阶段的时候,可以调用开发者预先设计好的回调函数去处理,这样效率比DOM方式更高。@H_301_4@


4.读取XML文件内容
//===================打开document===============add me ======
QString xmlPath = "filename.xml";
QFile file(xmlPath);
if (!file.open(QFile::ReadOnly | QFile::Text))
return ;@H_301_4@

QString errorStr;
int errorLine;
int errorColumn;@H_301_4@

QDomDocument doc;
if (!doc.setContent(&file,false,&errorStr,&errorLine,&errorColumn))
return ;
file.close();
//也可以用doc.setContent(&file)带一个参数就行。
//=============================================================@H_301_4@

然后按照上面方式遍历数据,修改后在以上面相同的方式写入到XML文件中。@H_301_4@


//=========================================附加一段代码 创建XML文件===============
int main( int argc,char **argv )
{
QApplication a( argc,argv );@H_301_4@

QString xmlPath = "InitInfo.xml";
QFile file(xmlPath);
if (!file.open(QFile::ReadOnly | QFile::Text))
return 1;
QString errorStr;
int errorLine;
int errorColumn;
QDomDocument doc;
if (!doc.setContent(&file,&errorColumn))
return 1;
file.close();@H_301_4@

QDomElement root = doc.documentElement();
QString str = root.tagName();
if (root.tagName() != "Root")
return 1;@H_301_4@

QDomElement element =doc.createElement_x_x("device3");
element.setAttribute("ChildName","Content");
QDomElement el_address = doc.createElement_x_x("Content ");
el_address.setAttribute("key","equipmentname");
el_address.setAttribute("value","CSC101B");
el_address.setAttribute("name","装置名称");
//QDomText text_address = doc.createTextNode("key");
//el_address.appendChild(text_address);@H_301_4@

element.appendChild(el_address);
QDomElement el_path = doc.createElement_x_x("path");
QDomText text_path = doc.createTextNode("aa");
el_path.appendChild(text_path);
element.appendChild(el_path);
root.appendChild(element);
QFile f(xmlPath);
if (!f.open(QFile::WriteOnly | QFile::Text))
return 1;
QTextStream out(&f);
QTextCodec * codec = QTextCodec::codecForName("GBK");
out.setCodec(codec);
QDomDocument xmlDoc;
QString strHead("version="1.0" encoding="GB2312"");
xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml",strHead));
out<<xmlDoc.toString();
root.save(out,3);
f.close();@H_301_4@

return 0; }@H_301_4@ 原文链接:https://www.f2er.com/xml/299866.html

猜你在找的XML相关文章