使用DOM创建和操作XML文档
版权声明
该文章原创于作者yafeilinux,转载请注明出处!
导语
环境:
Windows Xp + Qt 4.8.4+QtCreator 2.6.2
目录
一、创建文档
二、读取文档
三、添加节点
四、查找、删除、更新操作
正文
一、创建文档
2.
完成后打开myDom_2.pro
,然后将第一行代码更改为:
QT
+= coregui xml
保存该文件。
QFile
file("my.xml");
//
只写方式打开,并清空以前的信息
if
(!
file.open(QIODevice::WriteOnly | QIODevice::Truncate)) return ;
QDomDocument
doc;
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()
将各个节点依次追加进去。
QTextCodec
::setCodecForTr(
QTextCodec
::codecForName(
"utf8"
));
二、读取文档
void
MainWindow
::on_pushButton_5_clicked()
{
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();
//
下一个兄弟节点
}
}
运行程序,效果如下图所示。
三、添加节点
void
MainWindow
::on_pushButton_4_clicked()
{
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);
file.close();
}
这里先用只读方式打开XML文件,将其读入doc中,然后关闭。我们将新的节点加入到最后面,并使其“编号”为以前的最后一个节点的编号加1。最后我们再用只写的方式打开XML文件,将修改完的doc写入其中。运行程序,效果如下图所示。
再次查看全部信息,可以看到新的节点已经添加了,如下图所示。
四、查找、删除、更新操作
因为这三个功能都要先利用“编号”进行查找,所以我们放在一起实现。
1.
首先将界面上“图书编号”后面的Line Edit
部件的objectName
更改为lineEdit_id
。
void
doXml(
const
QString
operate);
我们使用这个函数来完成三种不同的操作,根据参数来判断不同的操作。
void
MainWindow
::doXml(
const
QString
operate)
{
ui
->
listWidget
->clear();
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())
{
{
QDomElement
root
=
doc.documentElement();
//
取出根节点
QFile
file(
"my.xml"
);
//
保存更改
if
(!file.open(
QIODevice
::
WriteOnly
|
QIODevice
::
Truncate
))
return ;
QTextStream
out(&file);
doc.save(out,
4
);
file.close();
ui
->
listWidget
->clear();
}
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());
}
}
}
}
}
//查找 voidMainWindow::on_pushButton_clicked() { doXml("find"); } //删除 voidMainWindow::on_pushButton_2_clicked() { doXml("delete"); } //更新void MainWindow::on_pushButton_3_clicked() { doXml("update"); }
下面运行程序,查找操作结果如下图所示。
然后对编号为1
的图书进行更新,效果如下图所示。
更新后我们再次查看所有内容。如下图所示。
然后进行删除操作,如下图所示。
结语
通过本节的例子可以看到使用DOM可以很方便的进行XML文档的随机访问,这也是它最大的优点。关于更多更详细的内容可以参考《Qt Creator快速入门》的相关章节。
涉及到的源码:myDom_2.zip |