接下来我们研究一下如何删除一个已有的子节点,并保存在文件里。

    这一节其实非常没有意思,为什么呢,因为其实我们想删除一个节点的某个子节点,直接用下面的代码就可以了:

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文件节点的程序。