XML语言数据读写理解7

225 阅读2分钟

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

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

`ABC.removeChild(realData.at(0));`

    ABC是之前定义的一个QDomElement元素,realData是子节点的列表。

   为了看看效果,我们还是从头开始。

首先给出test3.xml文件:

    然后我们想把这个文件读出来,然后把里面所有子节点的第一个元素删除,即: | | | 删除以后: | | 强烈建议从第一节开始看,里面所有的知识点都覆盖了,而且是教从零开始一行一行写把下面这个代码写出来的。

源代码贴上:其实就是根据前面几个小节写出来的读取文件改编的:

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