Qt代码实现解析xml文件到Qtreeview,通过右键菜单实现打开窗口编辑该xml的QDomdocument的属性编辑,并实现对节点的增删改从而改变xml文件的结构
时间: 2023-12-10 11:41:12 浏览: 154
这里提供一个简单的示例代码,演示如何使用Qt解析XML文件并将其显示在QTreeView中。同时,我们还将通过右键菜单实现打开编辑窗口来编辑XML节点属性,以及实现对节点的增删改。
首先,我们需要在Qt中创建一个新项目,选择Qt Widgets Application并设置名称和路径。接下来,我们需要在.ui文件中创建一个QTreeView和一个QMenu。我们还需要创建一个QDomDocument对象来保存XML文件的内容。
在mainwindow.h中,我们需要声明以下内容:
```cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDomDocument>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class QStandardItemModel;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void openFile();
void saveFile();
void editNode();
void addNode();
void removeNode();
private:
Ui::MainWindow *ui;
QDomDocument m_domDocument;
QStandardItemModel* m_model;
};
#endif // MAINWINDOW_H
```
在mainwindow.cpp中,我们需要实现以下内容:
```cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QStandardItemModel>
#include <QFile>
#include <QMessageBox>
#include <QMenu>
#include <QContextMenuEvent>
#include <QInputDialog>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, m_model(new QStandardItemModel(this))
{
ui->setupUi(this);
ui->treeView->setModel(m_model);
connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::openFile);
connect(ui->actionSave, &QAction::triggered, this, &MainWindow::saveFile);
QMenu* menu = new QMenu(this);
QAction* editAction = new QAction(tr("Edit"), this);
QAction* addAction = new QAction(tr("Add"), this);
QAction* removeAction = new QAction(tr("Remove"), this);
menu->addAction(editAction);
menu->addAction(addAction);
menu->addAction(removeAction);
connect(editAction, &QAction::triggered, this, &MainWindow::editNode);
connect(addAction, &QAction::triggered, this, &MainWindow::addNode);
connect(removeAction, &QAction::triggered, this, &MainWindow::removeNode);
ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->treeView, &QTreeView::customContextMenuRequested, [=](const QPoint& pos){
QModelIndex index = ui->treeView->indexAt(pos);
if (index.isValid())
{
menu->exec(ui->treeView->viewport()->mapToGlobal(pos));
}
});
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::openFile()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("XML Files (*.xml)"));
if (!fileName.isEmpty())
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly))
{
QMessageBox::critical(this, tr("Error"), tr("Could not open file for reading!"));
return;
}
if (!m_domDocument.setContent(&file))
{
file.close();
QMessageBox::critical(this, tr("Error"), tr("Could not parse XML file!"));
return;
}
file.close();
m_model->clear();
QDomNode root = m_domDocument.firstChild();
QStandardItem* item = new QStandardItem(root.nodeName());
m_model->appendRow(item);
for (QDomNode child = root.firstChild(); !child.isNull(); child = child.nextSibling())
{
parseNode(child, item);
}
}
}
void MainWindow::parseNode(const QDomNode& node, QStandardItem* parent)
{
QStandardItem* item = new QStandardItem(node.nodeName());
parent->appendRow(item);
if (node.hasAttributes())
{
QDomNamedNodeMap attributes = node.attributes();
for (int i = 0; i < attributes.count(); i++)
{
QDomNode attribute = attributes.item(i);
QStandardItem* attributeItem = new QStandardItem(attribute.nodeName() + "=\"" + attribute.nodeValue() + "\"");
item->appendRow(attributeItem);
}
}
for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling())
{
parseNode(child, item);
}
}
void MainWindow::saveFile()
{
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", tr("XML Files (*.xml)"));
if (!fileName.isEmpty())
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly))
{
QMessageBox::critical(this, tr("Error"), tr("Could not open file for writing!"));
return;
}
QTextStream stream(&file);
stream << m_domDocument.toString();
file.close();
}
}
void MainWindow::editNode()
{
QModelIndexList selected = ui->treeView->selectionModel()->selectedIndexes();
if (selected.count() != 1)
{
return;
}
QModelIndex index = selected.first();
QDomNode node = m_domDocument.elementsByTagName(index.parent().data().toString()).at(index.row());
QString attributeName = index.data().toString().split("=").first();
QString attributeValue = index.data().toString().split("=").last();
QString newValue = QInputDialog::getText(this, tr("Edit Attribute"), attributeName, QLineEdit::Normal, attributeValue);
if (!newValue.isEmpty())
{
node.toElement().setAttribute(attributeName, newValue);
m_model->clear();
QDomNode root = m_domDocument.firstChild();
QStandardItem* item = new QStandardItem(root.nodeName());
m_model->appendRow(item);
for (QDomNode child = root.firstChild(); !child.isNull(); child = child.nextSibling())
{
parseNode(child, item);
}
}
}
void MainWindow::addNode()
{
QModelIndexList selected = ui->treeView->selectionModel()->selectedIndexes();
if (selected.count() != 1)
{
return;
}
QModelIndex index = selected.first();
QDomNode parent = m_domDocument.elementsByTagName(index.parent().data().toString()).at(index.row());
QString nodeName = QInputDialog::getText(this, tr("Add Node"), tr("Node Name"), QLineEdit::Normal);
if (!nodeName.isEmpty())
{
QDomNode newNode = m_domDocument.createElement(nodeName);
parent.appendChild(newNode);
m_model->clear();
QDomNode root = m_domDocument.firstChild();
QStandardItem* item = new QStandardItem(root.nodeName());
m_model->appendRow(item);
for (QDomNode child = root.firstChild(); !child.isNull(); child = child.nextSibling())
{
parseNode(child, item);
}
}
}
void MainWindow::removeNode()
{
QModelIndexList selected = ui->treeView->selectionModel()->selectedIndexes();
if (selected.count() != 1)
{
return;
}
QModelIndex index = selected.first();
QDomNode node = m_domDocument.elementsByTagName(index.parent().data().toString()).at(index.row());
node.parentNode().removeChild(node);
m_model->clear();
QDomNode root = m_domDocument.firstChild();
QStandardItem* item = new QStandardItem(root.nodeName());
m_model->appendRow(item);
for (QDomNode child = root.firstChild(); !child.isNull(); child = child.nextSibling())
{
parseNode(child, item);
}
}
```
在这段代码中,我们首先在构造函数中创建了一个QMenu,并在其中添加三个QAction,分别用于编辑、添加和删除XML节点。然后,我们将QTreeView的上下文菜单策略设置为Qt::CustomContextMenu,并在customContextMenuRequested信号中弹出菜单。
在openFile函数中,我们首先使用QFileDialog打开XML文件。然后,我们使用QDomDocument对象解析XML文件。如果解析失败,则显示一个错误消息框。如果成功,则将解析后的XML节点添加到QStandardItemModel中,并在QTreeView中显示。
在saveFile函数中,我们使用QFileDialog打开对话框以获取要保存的文件名。然后,我们使用QTextStream将QDomDocument对象中的内容写入文件中。
在editNode函数中,我们首先检查用户是否只选择了一个XML节点。如果是,则使用QInputDialog获取用户要编辑的属性的新值。然后,我们使用QDomNode对象设置该属性的新值,并重新加载QStandardItemModel和QTreeView。
在addNode函数中,我们首先检查用户是否只选择了一个XML节点。如果是,则使用QInputDialog获取用户要添加的新节点的名称。然后,我们使用QDomNode对象创建一个新的XML节点,并将其添加到所选节点的子节点列表中。最后,我们重新加载QStandardItemModel和QTreeView。
在removeNode函数中,我们首先检查用户是否只选择了一个XML节点。如果是,则使用QDomNode对象删除该节点,并重新加载QStandardItemModel和QTreeView。
这就是一个简单的示例代码,演示如何使用Qt解析XML文件并将其显示在QTreeView中。同时,我们还演示了如何使用右键菜单编辑XML节点属性并添加或删除XML节点。
阅读全文