XML语言数据读写理解4
接着上一节来。首先再把xml文件放一下。
我们已经能显示出两个子节点Mode和Mode2来了,但是每个子节点底下也有属于它的子节点的子节点,即Mode里的firstEle和secondEle以及Mode2里的firstEle2和secondEle2,这两个节点应该怎么读取?我想应该已经很明确了:
QDomNode data = root.firstChild();
if (data.isNull()) {
//可以跟这个文件说再见了
}
while (!data.isNull())
{
QDomElement e = data.toElement(); // try to convert the node to an element.
dw->addContents("[" + e.tagName() + "]");
QDomNode numEle = data.firstChild();
while (!numEle.isNull()) {
QDomElement dd = numEle.toElement();
dw->addContents("[" + dd.tagName() + "]");
numEle = numEle.nextSiblingElement();
}
data = data.nextSiblingElement();
}
无非就是大循环里面套一个小循环嘛!显示如下:
[Mode]
[firstEle]
[secondEle]
[Mode2]
[firstEle2]
[secondEle2]
而每个firstEle以及secondEle里面都有好几个元素集,这些元素集都有值,即例如 id = "1",这些值可以用来作为每个数据的分类信息。例如你要设计一个数据显示的表格,每个人都对应了一组数据,人的序号从1排列到100,我们就设置数据的id为1到100,用来给每个人对应每套装备。
前面的Mode和firstEle其实都可以设置一些参数的,只是为了简单没有设置,现在我们需要解析一下带参数的元素了。
QDomNode data = root.firstChild();
if (data.isNull())
dw->addContents("error 3");
while (!data.isNull())
{
QDomElement e = data.toElement(); // try to convert the node to an element.
dw->addContents("[" + e.tagName() + "]");
QDomNode numEle = data.firstChild();
while (!numEle.isNull()) {
QDomElement dd = numEle.toElement();
dw->addContents("[" + dd.tagName() + "]");
QDomNode ABC = numEle.firstChild();
while (!ABC.isNull()) {
QDomElement abc = ABC.toElement();
dw->addContents("[" + abc.tagName() + "]" +"id: "+abc.attribute("id"));
ABC = ABC.nextSiblingElement();
}
numEle = numEle.nextSiblingElement();
}
data = data.nextSiblingElement();
}
大循环套中循环套小循环。
唯一不同的是小循环里面多了这么一句:
dw->addContents("[" + abc.tagName() + "]" +"id: "+abc.attribute("id"));
这一句可以把属性值打印出来。
之后我们发现,最小的子节点A , B 和 C里面是有元素的,我们需要用到节点列表把元素读取出来:
QDomNode data = root.firstChild();
if (data.isNull())
dw->addContents("error 3");
while (!data.isNull())
{
QDomElement e = data.toElement(); // try to convert the node to an element.
dw->addContents("[" + e.tagName() + "]");
QDomNode numEle = data.firstChild();
while (!numEle.isNull()) {
QDomElement dd = numEle.toElement();
dw->addContents("[" + dd.tagName() + "]");
QDomNode ABC = numEle.firstChild();
while (!ABC.isNull()) {
QDomElement abc = ABC.toElement();
dw->addContents("[" + abc.tagName() + "]" +"id: "+abc.attribute("id"));
if (!abc.isNull())
{
//将当前节点<Node>的所有元素放到QDomNodeList 中,以便遍历
QDomNodeList realData = ABC.childNodes();
for (int i = 0; i < realData.count(); i++)
{
QDomNode realDatanode = realData.at(i);
QString textname = realDatanode.toElement().tagName() + " param1: " + realDatanode.toElement().attribute("param1") +
" param2: " + realDatanode.toElement().attribute("param2") + " param3: " + realDatanode.toElement().attribute("param3");//查询属性值
dw->addContents(textname);
}
dw->addContents("");
}
ABC = ABC.nextSiblingElement();
}
numEle = numEle.nextSiblingElement();
}
data = data.nextSiblingElement();
}
也就是说在之前的最小循环里,加了这些代码:
if (!abc.isNull())
{
//将当前节点<Node>的所有元素放到QDomNodeList 中,以便遍历
QDomNodeList realData = ABC.childNodes();
for (int i = 0; i < realData.count(); i++)
{
QDomNode realDatanode = realData.at(i);
QString textname = realDatanode.toElement().tagName() + " param1: " + realDatanode.toElement().attribute("param1") +
" param2: " + realDatanode.toElement().attribute("param2") + " param3: " + realDatanode.toElement().attribute("param3");//查询属性值
dw->addContents(textname);
}
dw->addContents("");
}
使用列表,将里面所有的子节点都放进去,也就是XML里面的:
<T param1="42323" param2="2356" param3= "3d2"/>
<R param1="6256" param2="23562" param3= "f232f"/>
然后转化为元素,并将里面的属性值输出。
注意在写整个循环的之后不要把变量名弄混了,不然调试出错以后修改很麻烦!这充分说明了好的变量名以及好的数据结构的重要性。以后我们会专门使用结构来把这些数据进行读取和存储。
输出如下:
[Mode]
[firstEle]
[A]id: 1
T param1: 42323 param2: 2356 param3: 3d2
R param1: 6256 param2: 23562 param3: f232f
[A]id: 2
R param1: 433f3f param2: frsfs param3: f2g34g
R param1: 243442 param2: 324232 param3: j665
[B]id: 3
B param1: sdfsdfs param2: fef2 param3: 43tg
W param1: 123123 param2: 32ff param3: efea
[secondEle]
[C]id: 4
B param1: 143221 param2: kyr5y param3: fwf
B param1: 124531 param2: 4g4gs param3: 4w4g
[D]id: 5
B param1: 13231233 param2: 3qfgg param3: 44444tw
B param1: 45435 param2: aacevev param3: dghh
[Mode2]
[firstEle2]
[A]id: 1
T param1: 42323 param2: 2356 param3: 3d2
R param1: 6256 param2: 23562 param3: f232f
[A]id: 2
R param1: 433f3f param2: frsfs param3: f2g34g
R param1: 243442 param2: 324232 param3: j665
[B]id: 3
B param1: sdfsdfs param2: fef2 param3: 43tg
W param1: 123123 param2: 32ff param3: efea
[secondEle2]
[C]id: 4
B param1: 143221 param2: kyr5y param3: fwf
B param1: 124531 param2: 4g4gs param3: 4w4g
[D]id: 5
B param1: 13231233 param2: 3qfgg param3: 44444tw
B param1: 45435 param2: aacevev param3: dghh
为了显示美观,我们设置显示一下每个节点的结束标志,程序如下:
QDomNode data = root.firstChild();
if (data.isNull())
dw->addContents("error 3");
while (!data.isNull())
{
QDomElement e = data.toElement(); // try to convert the node to an element.
dw->addContents("[" + e.tagName() + "]");
QDomNode numEle = data.firstChild();
while (!numEle.isNull()) {
QDomElement dd = numEle.toElement();
dw->addContents("[" + dd.tagName() + "]");
QDomNode ABC = numEle.firstChild();
while (!ABC.isNull()) {
QDomElement abc = ABC.toElement();
dw->addContents("[" + abc.tagName() + "]" +"id: "+abc.attribute("id"));
if (!abc.isNull())
{
//将当前节点<Node>的所有元素放到QDomNodeList 中,以便遍历
QDomNodeList realData = ABC.childNodes();
for (int i = 0; i < realData.count(); i++)
{
QDomNode realDatanode = realData.at(i);
QString textname = realDatanode.toElement().tagName() + " param1: " + realDatanode.toElement().attribute("param1") +
" param2: " + realDatanode.toElement().attribute("param2") + " param3: " + realDatanode.toElement().attribute("param3");//查询属性值
dw->addContents(textname);
}
}dw->addContents("[/" + abc.tagName() + "]");
ABC = ABC.nextSiblingElement();
}dw->addContents("[/" + dd.tagName() + "]");
numEle = numEle.nextSiblingElement();
}dw->addContents("[/" + e.tagName() + "]");dw->addContents("");
data = data.nextSiblingElement();
}
显示效果:
[Mode]
[firstEle]
[A]id: 1
T param1: 42323 param2: 2356 param3: 3d2
R param1: 6256 param2: 23562 param3: f232f
[/A]
[A]id: 2
R param1: 433f3f param2: frsfs param3: f2g34g
R param1: 243442 param2: 324232 param3: j665
[/A]
[B]id: 3
B param1: sdfsdfs param2: fef2 param3: 43tg
W param1: 123123 param2: 32ff param3: efea
[/B]
[/firstEle]
[secondEle]
[C]id: 4
B param1: 143221 param2: kyr5y param3: fwf
B param1: 124531 param2: 4g4gs param3: 4w4g
[/C]
[D]id: 5
B param1: 13231233 param2: 3qfgg param3: 44444tw
B param1: 45435 param2: aacevev param3: dghh
[/D]
[/secondEle]
[/Mode]
[Mode2]
[firstEle2]
[A]id: 1
T param1: 42323 param2: 2356 param3: 3d2
R param1: 6256 param2: 23562 param3: f232f
[/A]
[A]id: 2
R param1: 433f3f param2: frsfs param3: f2g34g
R param1: 243442 param2: 324232 param3: j665
[/A]
[B]id: 3
B param1: sdfsdfs param2: fef2 param3: 43tg
W param1: 123123 param2: 32ff param3: efea
[/B]
[/firstEle2]
[secondEle2]
[C]id: 4
B param1: 143221 param2: kyr5y param3: fwf
B param1: 124531 param2: 4g4gs param3: 4w4g
[/C]
[D]id: 5
B param1: 13231233 param2: 3qfgg param3: 44444tw
B param1: 45435 param2: aacevev param3: dghh
[/D]
[/secondEle2]
[/Mode2]
至此,文件解析就全都完成了。一般而言设计xml文件解析程序都是按照自己的项目的数据结构进行设计的,除非为了显示,否则没有必要想办法设计一个通用的xml解析程序,不过也不难,无非就是遍历一下节点然后加一些判断罢了。下一节开始我们介绍如何写入xml文件。