QML Qt-解析XML并将其转换为LisView的ListModel

时间:2017-11-01 21:52:16

标签: c++ xml qt parsing qml

我是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文件时没有任何反应,但同样的文件被清理掉了#34;,变成了一个空白的.xml文件。 我怎样才能正确解析它,然后将解析后的数据转换为QML的ListView ListModel或任何可以支持QML编辑的模型?

- UPDATE - 解析XML文件将是一次性过程,在解析之后我打算使用javascript中的数据,因此如果可以在JSON对象结构中解析数据将会很酷。

2 个答案:

答案 0 :(得分:2)

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

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

如果您考虑做类似的事情,请不要永久回写。想想,什么时候做回写的好时机。一个明显的问题是当模型被摧毁时。但由于可能存在一些问题,因此无法正确销毁对象,您可能希望偶尔保存。

您可以使用计时器来保存,例如改变后的10秒(期待,如果发生一次变化,很快就会发生很多变化)

您可能还使用更复杂的XML格式,您确实只是追加基本记录更改。您不时会进行清理重写文件,以便丢失历史记录,但更改实际上会应用于您的xml结构。

答案 1 :(得分:0)

最后,我使用export default [ { ...Home, path:'/', exact:true }, { ...PublicLayout, path: '/public', // Added routes:[ { ...Profile, path:'/@:username', exact:true }, { ...PrivateLayout, routes:[ { ...TestBoard, path:'/home', exact:true }, { ...NewTest, path:'/test/:username', exact:true } ] }, ] }, { ...NotFound, }, ] 类来读取XML文件,遍历所有节点并将我想要的值写入JSON对象,如下所示:

QDomDocument

...

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