Qt4实现xml的读写操作

Qt4可以实现json操作,也可以实现xml文件操作。

xml文件主要有两种操作方式,1是dom操作,2是stream操作。

首先来看一下dom操作。

示例的文件如下:

<?xml version='1.0' encoding='UTF-8'?>
<文件库>
    <论文 编号="1">
        <标题>孙悟空</标题>
        <作者>看我72变</作者>
    </论文>
    <论文 编号="2">
        <标题>沙师弟</标题>
        <作者>不行吧</作者>
    </论文>
    <论文 编号="3">
        <标题>三藏</标题>
        <作者>阿弥陀佛</作者>
    </论文>
</文件库>

可以分为信息行,根节点和子节点。节点又分为tag和value,这和json是大致一样的。

首先是实现读取文件:

// 读xml文件
void Widget::on_pushButton_clicked()
{
    QString filename = getOpenFile();
    if(filename==QString(".xml")) return;
    readXml2List(filename);
}

// 获取文件名
QString Widget::getOpenFile()
{
    // 打开文件
    QString filedir = QCoreApplication::applicationDirPath();
    QString filename = QFileDialog::getOpenFileName(this,"打开xml文件",filedir,"xml (*.xml)");
    return filename;
}

// 读xml文件到domdoc对象
QDomDocument Widget::readXml(QString filename)
{
    QDomDocument doc;  // 创建Dom文档对象
    QFile file(filename);  // 创建文件对象
    if(!file.open(QIODevice::ReadOnly)) return doc;  // 打开文件对象 只读 如果出错就返回
    doc.setContent(&file);
    file.close();
    return doc;
}

// 读xml并显示
void Widget::readXml2List(QString filename)
{
    // 读xml文件到doc对象
    QDomDocument doc = readXml(filename);
    if(doc.toString()=="")
        return;
    ui->plainTextEdit->appendPlainText("已打开文件: "+filename+"\n");
    ui->plainTextEdit->appendPlainText(doc.toString());

    // 定义Dom节点对象 将第1个节点赋给他
    QDomNode firstNode = doc.firstChild();

    // 输出到text
    ui->plainTextEdit->appendPlainText(firstNode.nodeName()+": "+firstNode.nodeValue());

    // 返回根元素
    QDomElement docElem = doc.documentElement();

    // 返回根元素的第1个子节点
    QDomNode n = docElem.firstChild();

    // 如果节点不为空 则转到下1个节点
    while(!n.isNull())
    {
        // 如果节点是元素
        if(n.isElement())
        {
            // 将其转换为元素
            QDomElement e = n.toElement();

            // 返回元素标记和id属性值
            ui->plainTextEdit->appendPlainText(e.tagName()+": "+e.attribute("编号"));
            ui->listWidget->addItem(e.tagName()+": "+e.attribute("编号"));

            // 获得元素e的所有子节点列表
            QDomNodeList list = e.childNodes();

            // 遍历该列表
            for(int i = 0; i<list.count(); i++)
            {
                QDomNode node = list.at(i);
                if(node.isElement())
                {
                    ui->plainTextEdit->appendPlainText("  "+node.toElement().tagName()+": "+node.toElement().text());
                    ui->listWidget->addItem("  "+node.toElement().tagName()+": "+node.toElement().text());
                }
            }
        }
        // 转到下一个兄弟节点
        n = n.nextSibling();
    }
}

实现效果如下:

为了清晰展示读取效果,用list和plain两种方式来显示。

之后是写文件,先实现写示例:


// 写示例xml文件
void Widget::writeTestXml(QString filename)
{

    QDomDocument doc;

    // 添加xml说明
    QDomProcessingInstruction ins;
    ins = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
    doc.appendChild(ins);

    // 添加根元素
    QDomElement root = doc.createElement(QString("文件库"));
    doc.appendChild(root);

    // 添加第1个文献元素及其子元素
    QDomElement paper = doc.createElement(QString("论文"));
    QDomAttr id = doc.createAttribute(QString("编号"));
    QDomElement title = doc.createElement(QString("标题"));
    QDomElement author = doc.createElement(QString("作者"));
    QDomText text;
    id.setValue(QString("1"));
    paper.setAttributeNode(id);
    text = doc.createTextNode(QString("三国演义"));
    title.appendChild(text);
    text = doc.createTextNode(QString("罗贯中"));
    author.appendChild(text);
    paper.appendChild(title);
    paper.appendChild(author);
    root.appendChild(paper);

    // 添加第2个文献元素及其子元素
    paper = doc.createElement(QString("论文"));
    id = doc.createAttribute(QString("编号"));
    title = doc.createElement(QString("标题"));
    author = doc.createElement(QString("作者"));
    id.setValue(QString("2"));
    paper.setAttributeNode(id);
    text = doc.createTextNode(QString("茶馆"));
    title.appendChild(text);
    text = doc.createTextNode(QString("老舍"));
    author.appendChild(text);
    paper.appendChild(title);
    paper.appendChild(author);
    root.appendChild(paper);

    // 写doc到xml文件
    writeXml(filename, doc);
}

写文件之后,马上调用读文件来显示:

最后,在实现一下节点的增删改查:

代码如下:


void Widget::doXml(QString filename, const QString operate)
{
    // 读xml文件到doc
    QDomDocument doc = readXml(filename);

    if(doc.toString()=="") return;

    // 以标签名进行查找
    QDomNodeList list = doc.elementsByTagName(QString("论文"));

    for(int i = 0; i<list.count(); i++)
    {
        QDomElement e = list.at(i).toElement();
        // 如果属性值相同
        if(e.attribute(QString("编号"))==ui->lineEdit_3->text())
        {
            if(operate=="delete")
            {
                QDomElement root = doc.documentElement();
                root.removeChild(list.at(i));// 从根节点删除
                writeXml(filename,doc);
                ui->listWidget->clear();
                readXml2List(filename);
            }
            else if(operate=="update")
            {
                QDomNodeList child = list.at(i).childNodes();
                child.at(0).toElement().firstChild().setNodeValue(ui->lineEdit->text());
                child.at(1).toElement().firstChild().setNodeValue(ui->lineEdit_2->text());
                writeXml(filename,doc);
                ui->listWidget->clear();
                readXml2List(filename);
            }
            else if(operate=="find")
            {
                ui->listWidget->addItem(e.tagName()+e.attribute(QString("编号")));
                QDomNodeList childlist = e.childNodes();
                for(int i = 0; i<childlist.count(); i++)
                {
                    QDomNode node = childlist.at(i);
                    ui->listWidget->clear();
                    ui->listWidget->addItem("  "+node.toElement().tagName()+": "+node.toElement().text());
                }
            }
        }
    }

}

 

总结:dom操作可以便捷的实现增删改查。用这种方式可以满足文件model的信息表建立。

疑问:如何使用model形式在listview或者treeview上显示呢,怎么弄mvc

如何实现在treewidget上的显示?

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Intimes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值