使用DOM创建和操作XML文档
版权声明
该文章原创于作者yafeilinux,转载请注明出处!
导语
在上一节中我们用手写的方法建立了一个XML文档,并且用DOM的方法对其进行了读取。现在我们使用代码来创建那个XML文档,并且对它实现查找、更新、插入等操作。
环境:
Windows Xp + Qt 4.8.4+QtCreator 2.6.2
目录
一、创建文档
二、读取文档
三、添加节点
四、查找、删除、更新操作
正文
一、创建文档
1.
新建Qt Gui 应用,项目名称为myDom_2 ,基类为QMainWindow ,类名为MainWindow 。
2.
完成后打开myDom_2.pro ,然后将第一行代码更改为:
QT
+= core gui xml 保存该文件。
3.
双击mainwindow.ui 进入设计模式,往界面上添加Push Button ,Label ,Line Edit ,List Widget 等部件,设计界面如下图所示。
4.
完成后,打开mainwindow.cpp 文件,先包含头文件 #include <QtXml> ,然后在构造函数中添加如下代码:
QFile
file("my.xml");
//
只写方式打开,并清空以前的信息
if
(! file.open(QIODevice::WriteOnly | QIODevice::Truncate)) return ;
QDomDocument
doc;
QDomProcessingInstruction
instruction; // 添加处理指令
instruction = doc.createProcessingInstruction("xml",
"version=\\"1.0\\"encoding=\\"UTF-8\\"");
doc.appendChild(instruction);
QDomElement
root = doc.createElement(tr(" 书库" ));
doc.appendChild(root); //
添加根元素
//
添加第一个book元素及其子元素
QDomElement
book = doc.createElement(tr(" 图书" ));
QDomAttr
id = doc.createAttribute(tr(" 编号" ));
QDomElement
title = doc.createElement(tr(" 书名" ));
QDomElement
author = doc.createElement(tr(" 作者" ));
QDomText
text;
id.setValue(tr("1"));
book.setAttributeNode(id);
text = doc.createTextNode(tr("Qt"));
title.appendChild(text);
text = doc.createTextNode(tr("shiming"));
author.appendChild(text);
book.appendChild(title);
book.appendChild(author);
root.appendChild(book);
//
添加第二个book元素及其子元素
book = doc.createElement(tr("
图书" ));
id = doc.createAttribute(tr("
编号" ));
title = doc.createElement(tr("
书名" ));
author = doc.createElement(tr("
作者" ));
id.setValue(tr("2"));
book.setAttributeNode(id);
text = doc.createTextNode(tr("Linux"));
title.appendChild(text);
text = doc.createTextNode(tr("yafei"));
author.appendChild(text);
book.appendChild(title);
book.appendChild(author);
root.appendChild(book);
QTextStream
out(&file);
doc.save(out,4); //
将文档保存到文件,4为子元素缩进字符数
file.close();
这里先使用QDomDocument 类在内存中生成了一棵DOM 树,然后调用save() 函数利用QTextStream 文本流将DOM 树保存在了文件中。在生成DOM 树时主要使用了createElement() 等函数来生成各种节点,然后使用appendChild() 将各个节点依次追加进去。
5.
打开main.cpp 文件,先包含头文件: #include <QTextCodec> ,然后在main() 函数第一行代码后面添加如下代码:
QTextCodec
::setCodecForTr( QTextCodec ::codecForName( "utf8" ));
6.
运行程序,可以看到在构建目录中生成了my.xml 文件,可以双击查看该文件的内容,效果如下图所示。
二、读取文档
下面我们读取整个文档的内容,并显示在List Widget 部件上面,这里用的就是上一节讲到的内容。我们进入“查看全部信息”按钮单击信号槽,更改如下:
void
MainWindow ::on_pushButton_5_clicked()
{
ui -> listWidget->clear(); // 先清空显示 QFile file( "my.xml" ); if (!file.open( QIODevice :: ReadOnly )) return ; QDomDocument doc; if (!doc.setContent(&file)) { file.close(); return ; }
file.close();
// 返回根节点及其子节点的元素标记名 QDomElement docElem = doc.documentElement(); // 返回根元素 QDomNode n = docElem.firstChild(); // 返回根节点的第一个子节点 while (!n.isNull()) // 如果节点不为空 { if (n.isElement()) // 如果节点是元素 { QDomElement e = n.toElement(); // 将其转换为元素 ui -> listWidget->addItem(e.tagName()
+e.attribute(tr("编号")));
QDomNodeList list = e.childNodes(); for ( int i= 0 ; i<list.count(); i++) { QDomNode node = list.at(i); if (node.isElement()) ui -> listWidget->addItem(" "
+node.toElement().tagName()
+ " : " +node.toElement().text()); } } n = n.nextSibling(); // 下一个兄弟节点 }
}
运行程序,效果如下图所示。
三、添加节点
1.
首先在设计模式,把书名和作者标签后面的Line Edit 部件的objectName 分别更改为lineEdit_title 和lineEdit_author 。如下图所示。
2.
然后进入添加按钮的单击信号槽,添加如下代码:
void
MainWindow ::on_pushButton_4_clicked()
{
ui -> listWidget ->clear(); // 我们先清空显示,然后显示“无法添加!” ui -> listWidget ->addItem(tr( " 无法添加!" )); QFile file( "my.xml" ); if (!file.open( QIODevice :: ReadOnly )) return ; QDomDocument doc; if (!doc.setContent(&file)) { file.close(); return ; } file.close(); QDomElement root = doc.documentElement(); QDomElement book = doc.createElement(tr( " 图书" )); QDomAttr id = doc.createAttribute(tr( " 编号" )); QDomElement title = doc.createElement(tr( " 书名" )); QDomElement author = doc.createElement(tr( " 作者" )); QDomText text; // 我们获得了最后一个孩子结点的编号,然后加1,便是新的编号 QString num = root.lastChild().toElement().attribute(tr( " 编号" )); int count = num.toInt() + 1 ; id.setValue( QString ::number(count)); book.setAttributeNode(id); text = doc.createTextNode( ui -> lineEdit_title ->text()); title.appendChild(text); text = doc.createTextNode( ui -> lineEdit_author ->text()); author.appendChild(text); book.appendChild(title); book.appendChild(author); root.appendChild(book); if (!file.open( QIODevice :: WriteOnly | QIODevice :: Truncate )) return ; QTextStream out(&file); doc.save(out, 4 ); // 将文档保存到文件,4为子元素缩进字符数 file.close(); ui -> listWidget ->clear(); // 最后更改显示为“添加成功!” ui -> listWidget ->addItem(tr( " 添加成功!" ));
}
这里先用只读方式打开XML文件,将其读入doc中,然后关闭。我们将新的节点加入到最后面,并使其“编号”为以前的最后一个节点的编号加1。最后我们再用只写的方式打开XML文件,将修改完的doc写入其中。运行程序,效果如下图所示。
再次查看全部信息,可以看到新的节点已经添加了,如下图所示。
四、查找、删除、更新操作
因为这三个功能都要先利用“编号”进行查找,所以我们放在一起实现。
1.
首先将界面上“图书编号”后面的Line Edit 部件的objectName 更改为lineEdit_id 。
2.
在mainwindow.h 文件中添加public 类型的函数声明: void doXml( const QString operate);
我们使用这个函数来完成三种不同的操作,根据参数来判断不同的操作。
3.
然后到mainwindow.cpp 中添加该函数的定义:
void
MainWindow ::doXml( const QString operate)
{
ui -> listWidget ->clear(); ui -> listWidget ->addItem(tr( " 没有找到相关内容!" )); QFile file( "my.xml" ); if (!file.open( QIODevice :: ReadOnly )) return ; QDomDocument doc; if (!doc.setContent(&file)) { file.close(); return ; } file.close();
QDomNodeList list = doc.elementsByTagName(tr( " 图书" )); // 以标签名进行查找 for ( int i= 0 ; i<list.count(); i++) { QDomElement e = list.at(i).toElement(); // 如果元素的“编号”属性值与我们所查的相同 if (e.attribute(tr( " 编号" )) == ui -> lineEdit_id ->text()) { // 如果元素的“编号”属性值与我们所查的相同 if (operate == "delete" ) // 如果是删除操作 { QDomElement root = doc.documentElement(); // 取出根节点 root.removeChild(list.at(i)); // 从根节点上删除该节点 QFile file( "my.xml" ); // 保存更改 if (!file.open( QIODevice :: WriteOnly | QIODevice :: Truncate )) return ; QTextStream out(&file); doc.save(out, 4 ); file.close(); ui -> listWidget ->clear(); ui -> listWidget ->addItem(tr( " 删除成功!" )); } else if (operate == "update" ) // 如果是更新操作 { QDomNodeList child = list.at(i).childNodes(); // 找到它的所有子节点,就是“书名”和“作者” child.at( 0 ).toElement().firstChild().setNodeValue( ui->lineEdit_title->text()); // 将它子节点的首个子节点(就是文本节点)的内容更新 child.at( 1 ).toElement().firstChild().setNodeValue( ui->lineEdit_author->text()); QFile file( "my.xml" ); // 保存更改 if (!file.open( QIODevice :: WriteOnly | QIODevice :: Truncate )) return ; QTextStream out(&file); doc.save(out, 4 ); // 保存文档,4为子元素缩进字符数 file.close(); ui -> listWidget ->clear(); ui -> listWidget ->addItem(tr( " 更新成功!" )); } else if (operate == "find" ) // 如果是查找操作 { ui -> listWidget ->clear(); ui -> listWidget ->addItem(e.tagName() +e.attribute(tr("编号"))); QDomNodeList list = e.childNodes(); for ( int i= 0 ; i<list.count(); i++) { QDomNode node = list.at(i); if (node.isElement()) ui -> listWidget ->addItem( " " +node.toElement().tagName() + " : " +node.toElement().text()); } } } }
}
4.
下面我们分别进入“ 查找” ,“ 删除” ,“ 更新” 三个按钮的单击信号槽,更改如下: // 查找 // 删除 // 更新void
下面运行程序,查找操作结果如下图所示。
然后对编号为1
的图书进行更新,效果如下图所示。
更新后我们再次查看所有内容。如下图所示。
然后进行删除操作,如下图所示。
删除后再次查询所有内容。效果如下图所示。
结语
通过本节的例子可以看到使用DOM可以很方便的进行XML文档的随机访问,这也是它最大的优点。关于更多更详细的内容可以参考《Qt Creator快速入门》的相关章节。
涉及到的源码: myDom_2.zip |
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容