接下来我们研究一下如何删除一个已有的子节点,并保存在文件里。
这一节其实非常没有意思,为什么呢,因为其实我们想删除一个节点的某个子节点,直接用下面的代码就可以了:
ABC.removeChild(realData.at(0));
ABC是之前定义的一个QDomElement元素,realData是子节点的列表。
为了看看效果,我们还是从头开始。
首先给出test3.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Appearance>
<ROOT>
<Mode>
<firstEle>
<A id = "1">
<T param1="42323" param2="2356" param3= "3d2"/>
<R param1="6256" param2="23562" param3= "f232f"/>
</A> <!-- childNode.nextSibling() 寻找下一个兄弟节点 -->
<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> <!-- childNode.nextSibling() 寻找下一个兄弟节点 -->
<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>
</ROOT>
然后我们想把这个文件读出来,然后把里面所有子节点的第一个元素删除,即:
<A id = "1">
<T param1="42323" param2="2356" param3= "3d2"/>
<R param1="6256" param2="23562" param3= "f232f"/>
</A>
|
|
| 删除以后:
|
|
<A id = "1">
<R param1="6256" param2="23562" param3= "f232f"/>
</A>
强烈建议从第一节开始看,里面所有的知识点都覆盖了,而且是教从零开始一行一行写把下面这个代码写出来的。
源代码贴上:其实就是根据前面几个小节写出来的读取文件改编的:
DebugWidget *dw = new DebugWidget;
//QDomDocument xml;
//xml.setContent(QString("test2.xml"));
QDomDocument xml("test3");
QFile file("C:\\Developer\\Rendering\\Rendering\\XML\\test3.xml");
if (!file.open(QIODevice::ReadOnly))
dw->addContents("error 1");
if (!xml.setContent(&file))
{
file.close();
dw->addContents("error 2");
}
file.close();
//这里有类似于version这样的第一个子节点信息。
QDomNode firstChild = xml.firstChild();
if (firstChild.nodeName()=="xml") {
dw->addContents(firstChild.nodeName());
dw->addContents(firstChild.nodeValue());
}
else {
dw->addContents("No version , No Format");
}
dw->addContents("");
//读取根元素<Mode>
QDomElement root = xml.documentElement();
dw->addContents("["+root.tagName()+"]");
dw->addContents("");
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();
if(numEle.isElement())dw->addContents("It is an element");
while (!numEle.isNull()) {
QDomElement dd = numEle.toElement();
dw->addContents("[" + dd.tagName() + "]");
QDomNode ABC = numEle.firstChild();
if (ABC.isElement())dw->addContents("It is an element");
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);
}
ABC.removeChild(realData.at(0));
}dw->addContents("[/" + abc.tagName() + "]");
ABC = ABC.nextSiblingElement();
}dw->addContents("[/" + dd.tagName() + "]");
numEle = numEle.nextSiblingElement();
}dw->addContents("[/" + e.tagName() + "]");dw->addContents("");
data = data.nextSiblingElement();
}
QString fileName{ "C:\\Developer\\Rendering\\Rendering\\XML\\test4.xml" };
QFile file2(fileName);
if (!file2.open(QIODevice::WriteOnly | QIODevice::Text))
{
qDebug() << "open for add error!!";
}
//输出到文件
QTextStream out_stream(&file2);
xml.save(out_stream, 4); //缩进4格
file2.close();
相比以前,只增加了这么几句:
ABC.removeChild(realData.at(0));
以及最后把文件写进去的程序:
QString fileName{ "C:\\Developer\\Rendering\\Rendering\\XML\\test4.xml" };
QFile file2(fileName);
if (!file2.open(QIODevice::WriteOnly | QIODevice::Text))
{
qDebug() << "open for add error!!";
}
//输出到文件
QTextStream out_stream(&file2);
xml.save(out_stream, 4); //缩进4格
file2.close();
显示效果如下,可以看到每个最底层节点的第一个元素被删除了:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Appearance>
<ROOT>
<Mode>
<firstEle>
<A id="1">
<R param2="23562" param3="f232f" param1="6256"/>
</A>
<!-- childNode.nextSibling() 寻找下一个兄弟节点 -->
<A id="2">
<R param2="324232" param3="j665" param1="243442"/>
</A>
<B id="3">
<W param2="32ff" param3="efea" param1="123123"/>
</B>
</firstEle>
<secondEle>
<C id="4">
<B param2="4g4gs" param3="4w4g" param1="124531"/>
</C>
<D id="5">
<B param2="aacevev" param3="dghh" param1="45435"/>
</D>
</secondEle>
</Mode>
<Mode2>
<firstEle2>
<A id="1">
<R param2="23562" param3="f232f" param1="6256"/>
</A>
<!-- childNode.nextSibling() 寻找下一个兄弟节点 -->
<A id="2">
<R param2="324232" param3="j665" param1="243442"/>
</A>
<B id="3">
<W param2="32ff" param3="efea" param1="123123"/>
</B>
</firstEle2>
<secondEle2>
<C id="4">
<B param2="4g4gs" param3="4w4g" param1="124531"/>
</C>
<D id="5">
<B param2="aacevev" param3="dghh" param1="45435"/>
</D>
</secondEle2>
</Mode2>
</ROOT>
正如前面所说的,其实没有什么意思,就是在里面加个删除语句罢了,添加节点就更容易了,直接在节点中使用appendChild就能给该节点增加一个子节点,但是这肯定不是我们想要的。如果想真正做到自由删除节点,我们必须要根据自己操作的数据进行一定的封装。
下一章节就开始自己根据具体实例写一个数据结构来读取,写入,以及更改,删除xml文件节点的程序。