【问题标题】:QML Qt- Parse XML and convert it as a LisView's ListModelQML Qt- 解析 XML 并将其转换为 LisView 的 ListModel
【发布时间】:2017-11-01 21:52:16
【问题描述】:

我是 Qt 和 QML 的新手。话虽如此,我正在 QML 中制作一个可编辑的列表,我想将其导入和导出为 XML 文件。现在我坚持从 XML 文件中导入它并从 C++ 端将其设置为我的ListView 模型。

我希望我可以将 XML 转换为表单 我希望能够从 QML 端添加、删除和编辑我的 ListView 中的行,因此使用 XmlListModel 看起来是个坏主意,即它不提供这些功能。

我在其中选择文件位置的 main.qml:

    FileDialog {
        id: exportDialog
        title: "Please choose an XML TV file"
        nameFilters: [("*.xml")]

        onAccepted: {
            fileio.parse(importDialog.fileUrl)
        }
        onRejected: {
            console.log("Canceled")
        }
    }

我希望在其中进行转换的 C++ 头文件:

#ifndef FILEIO_H
#define FILEIO_H

#include <QObject>
#include <QFile>
#include <QTextStream>
#include <QXmlStreamReader>
#include <QDebug>

class FileIO : public QObject
{
    Q_OBJECT

public slots:
    bool parse(const QString& source)
    {
        if (source.isEmpty())
            return false;

        QFile file(source);
        if (!file.open(QFile::WriteOnly | QFile::Truncate))
            return false;    

        QFile* mjau = new QFile(source);
        if (!mjau->open(QIODevice::ReadOnly | QIODevice::Text)) {
                printf("Load XML File Problem");
                return false;
        }

        QXmlStreamReader reader(mjau);
        while(!reader.atEnd() && !reader.hasError()) {
            if(reader.readNext() == QXmlStreamReader::StartElement && reader.name() == "parent") {
                 qDebug() << reader.readElementText();
                //printf(reader.readElementText())
            }
        }
    }
public:
    FileIO() {}
};

#endif // FILEIO_H

我要解析的 xml 文件示例,大量条目:

<notes>
    <note>
        <heading>Help</heading>
        <body>I want to make this work!</body>
    </note>
    <note>
        <heading>Because</heading>
        <body>I love QML <3</body>
    </note>
    ...
</notes>

这样的:

ListModel {
    id: notes
    ListElement {
        heading: "Help"
        body: "I want to make this work!"
    }
    ListElement {
        heading: "Because"
        body: "I love QML <3"
    }
}

现在,当我选择 XML 文件时,什么也没有发生,但是同一个文件被“清除”,变成了一个空白的 .xml 文件。 如何正确解析它,然后将解析后的数据转换为 QML 的 ListView ListModel 或任何可以支持 QML 侧编辑的模型?

--更新-- XML文件的解析将是一个一次性的过程,在解析之后我打算在javascript中处理数据,所以如果数据可以在JSON对象结构中解析会很酷。

【问题讨论】:

    标签: c++ xml qt parsing qml


    【解决方案1】:

    您不应将其转换为ListModel。而是实现您自己的具有所需功能的 QAbstractListModel 的后代。

    但是,Qt 确实将XmlListModel 提供为只读可能是有原因的。 You can't just insert into a file. (AFAIK) 因此,如果添加或删除了一个条目,并且该更改不在文件的最后,则需要复制整个内容。当数据发生变化时,就需要这样做。不利于性能。

    如果您考虑这样做,请不要永久回信。想想,什么时候是做回写的好时机。一个明显的点是模型被破坏的时候。但由于可能存在一些问题,无法正常销毁该对象,您可能需要时不时地保存。

    您可以使用计时器来保存,例如更改后 10 秒(预计如果发生一个更改,很快就会发生许多更改)

    您还可以对 XML 使用更复杂的格式,实际上您只是在其中添加了基本的更改记录。您不时地做一个清理重写文件,这样历史就丢失了,但更改确实应用于您的 xml 结构。

    【讨论】:

    • 所有有效积分。但是,我打算使用非常小的 xml 文件,大小为 100-200kb。但即使这不是问题,我也非常愿意接受任何可以以更可编辑的形式解析 xml 文件的方法,无论是像 @eyllanesc 评论的 sqlite 数据库,还是简单的 JSON 对象模型。在我从 XML 中获取数据后,以后可以轻松地对其进行操作。解析是我现在困扰的问题。
    【解决方案2】:

    最后,我使用QDomDocument 类来读取 XML 文件,遍历所有节点并将我想要的值写入 JSON 对象,如下所示:

    QDomElement root = doc.firstChildElement();
    QDomNodeList programme = root.elementsByTagName("node");
    nodeCollection.push_back(ListElements(program, "title", "lang"));
    

    ...

    QJsonObject ListElements (QDomElement root, QString tagname, QString attribute)
    {
    
            QDomNodeList items = root.elementsByTagName(tagname);
    
            for(int i = 0; i < items.count(); i++)
            {
                QDomNode itemnode = items.at(i);
                if (itemnode.isElement())
                {
                    QDomElement itemElement = itemnode.toElement();
                    qInfo() << itemElement.tagName(); // <-element name
                    qInfo() << itemElement.attribute("lang"); // <-element attribute
                    qInfo() << itemElement.text(); // <-element text
    
    // putting the values above inside JSOn object:
    
                    auto nodeData = QJsonObject(
                    {
                    qMakePair(QString(itemElement.tagName()), QJsonValue(itemElement.text())),
                    qMakePair(QString("lang"), QJsonValue(itemElement.attribute("lang"))),
                    });
    
                    return nodeData;
                }
            }
        }
    

    所以这个:

      <node>
        <title lang="en">Title1</title>
        <category lang="en">Category1</category>
        <desc lang="en">Description1</desc>
      </node>
    

    变成(这是ListElements 返回的):

     QJsonObject({"title":"Title1","lang":"en"})
     QJsonObject({"category":"Category1","lang":"en"})
     QJsonObject({"desc":"Description1","lang":"en"})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-29
      • 1970-01-01
      • 1970-01-01
      • 2021-10-29
      相关资源
      最近更新 更多