C++
QT以DOM方式读写XML
  • By刘立博
  • 2020-12-19 23:23:31
  • 964人已阅读

DOM方式读写XML的优劣

由于需要将 XML 文档转换为树形结构存储到内存中,所以内存占用较大.但操作方便,适合频繁读写的场景

 

QDomDocument

QT所有对XML的操作方法均封装在QDomDocument之中,要使用QDomDocument需要添加XML模块

 

添加XML模块

编辑QT项目配置文件xmlBom.pro,在已添加的模块后追加XML模块

QT       += core gui xml

 

QDomDocument常用方法及示例

 

createProcessingInstruction

创建一个可以插入到XML文档的Dom头声明

示例

声明dom头<?xml version="1.0" encoding="UTF-8"?>

doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");

 

 

createElement

创建一个可以插入DOM树的元素节点

示例

如创建一个名为users的元素节点

QDomElement body = doc.createElement("users");

 

 

 

createTextNode

创建一个文本节点(设置节点的正文)

示例

设置元素节点name的正文为"my name"

QDomElement user_name = doc.createElement("name");
user_name.appendChild(doc.createTextNode("my name"));

 

 

 

setAttribute

设置节点属性

示例

设置name节点gender属性为male

QDomElement user_name = doc.createElement("name");
user_name.setAttribute("gender","male");

 

 

appendChild

将节点追加至某个节点

示例

将body节点追加至doc节点(设置子节点)

doc.appendChild(body);

 

 

setContent

将byte数组解析为XML DOM树

示例

将一个XML文件解析为DOM树

doc.setContent(xmlFile);

 

 

 

documentElement

获取XML文档的根节点

示例

获取DOM doc中的根节点

QDomElement root = doc.documentElement();

 

 

 

childNodes

获取某节点下的子节点列表

示例

获取root节点下的子节点列表

QDomNodeList userList = doc.documentElement().childNodes();

 

 

 

toElement

将节点对象转为元素对象

示例

将user节点下的第一个子节点转为元素对象

QDomNodeList eleList = user.childNodes();
QDomElement name = eleList.at(0).toElement();

 

 

Text

获取转为元素对象节点的正文

示例

获取元素name的正文

QDomElement name = eleList.at(0).toElement();
Qstring nameText = name.text();

 

Attribute

获取转为元素对象节点的属性

示例

获取元素name中gender属性的值

QDomElement name = eleList.at(0).toElement();
String genderValue = name.attribute("gender");

 

 

一个栗子:读取\写入一个用户列表XML文件

 

XML文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE users>
<users>
    <user>
        <name gender="male">张三</name>
        <age>18</age>
    </user>
    <user>
        <name gender="female">李四</name>
        <age>19</age>
    </user>
    <user>
        <name gender="male">王五</name>
        <age>20</age>
    </user>
</users>

 

写入XML文件

用户选择文件保存路径后,构建DOM树,写入XML文件

void MainWindow::on_pushButton_2_clicked()
{
    QString path = QFileDialog::getSaveFileName(this,"请选择一个XML文件",QDir::currentPath(),"XML(*.xml)");
    if(path.isEmpty()) QMessageBox::critical(this,"打开文件失败","请选择一个XML文件");
    xmlFile->setFileName(path);
    xmlFile->open(QIODevice::WriteOnly);

    QDomDocument doc("users");
    QDomProcessingInstruction header = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
    doc.appendChild(header);

    QDomElement body = doc.createElement("users");

    // user
    QStringList arrayNames;
    arrayNames << "张三" << "李四" << "王五";
    QStringList arrayGenders;
    arrayGenders << "male" << "female" << "male";
    QStringList arrayAges ;
    arrayAges << "18" << "19" << "20";

    for(int i=0;i<arrayNames.size();i++)
    {
        QDomElement user = doc.createElement("user");

        QDomElement user_name = doc.createElement("name");
        user_name.setAttribute("gender",arrayGenders.at(i));
        user_name.appendChild(doc.createTextNode(arrayNames.at(i)));
        QDomElement user_age = doc.createElement("age");
        user_age.appendChild(doc.createTextNode(arrayAges.at(i)));

        user.appendChild(user_name);
        user.appendChild(user_age);
        body.appendChild(user);
    }

    doc.appendChild(body);

    //save file
    QTextStream stream(xmlFile);
    stream.setCodec("UTF-8");
    doc.save(stream,4);
    QMessageBox::information(this,"保存成功",xmlFile->fileName());
    xmlFile->close();
}

测试效果

 

 

读取XML文件

用户选择文件读取路径后,将XML转为DOM树,迭代并显示XML文件内容

 

void MainWindow::on_pushButton_1_clicked()
{
    QString path = QFileDialog::getOpenFileName(this,"请选择一个XML文件",QDir::currentPath(),"XML(*.xml)");
    if(path.isEmpty()) QMessageBox::critical(this,"打开文件失败","请选择一个XML文件");
    xmlFile->setFileName(path);
    xmlFile->open(QIODevice::ReadOnly);

    QDomDocument doc("users");
    doc.setContent(xmlFile);
    xmlFile->close();

    QDomNodeList userList = doc.documentElement().childNodes();
    for(int i = 0;i<userList.size();i++)
    {
        QDomNode user = userList.at(i);
        QDomNodeList eleList = user.childNodes();

        QDomElement name = eleList.at(0).toElement();
        QDomElement age = eleList.at(1).toElement();

        ui->plainTextEdit->appendPlainText(
                    " name: "+name.text()+
                    " gander:"+name.attribute("gender")+
                    " age:"+age.text()+"\r\n"
        );
    }
}

 

测试效果