2

因此,我试图通读一个中等大小的 XML 文档。它的结构如下:

<project identifier="project1">
    <author>Joe Smith</author>
    <author2>Rick Jones</author2>
    <path>projects/internal/project2</path>
    <version>1.51</version>
</project>
<project identifier="project2">
     <author>Terry Chimes</author>
     <author>Janie Jones</author>
     <path>projects/external/project2</path>
     <version>19.77</version>
</project>

...等等,用于数百个项目。

我正在使用 Qt5.10's QXmlStreamReader,它可能是由虐待狂创建(或记录)的。

我可以project通过使用xmlReader.readNextStartElement- 或逐个标签地读取每个标签,直到找到一个具有内部属性的标签(只有project标签在此文件中具有属性)。

但是,一旦我阅读了这些父元素中的一个,它就会QXmlStreamReader吸收每个标签直到它的结束</project>标签。问题是我需要获取其中的一些数据,在这种情况下,是<path></path>标签内的内容。

我可以用 检索所有的数据xmlReader.readElementText(QXmlStreamReader::IncludeChildElements,但这只是一个没有标签的大数据转储。

有谁知道我如何“倒带”并阅读内部标签?或者阻止流读取器向前倾斜并吸收所有数据?

4

1 回答 1

4

最可能的解释是你做错了什么,QXmlStreamReader在解析文档时不应该跳过内部元素。您还没有提供任何源代码,因此无法说出您到底做错了什么。

这是我的代码示例,它非常适用于与您在 macOS 10.13.2 上使用 Qt 5.9.2 的示例非常相似:

#include <QCoreApplication>
#include <QDebug>
#include <QXmlStreamReader>
#include <QFile>
#include <QHash>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    if (argc != 2) {
        qWarning() << "Usage: " << argv[0] << " <file>";
        return 1;
    }

    QFile file(argv[1]);
    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "Failed to open file " << argv[1] << " for reading";
        return 1;
    }

    QXmlStreamReader reader(&file);
    QString currentProjectId;
    QHash<QString,QString> pathByProjectId;
    while(!reader.atEnd())
    {
        reader.readNext();

        if (reader.isStartDocument()) {
            continue;
        }

        if (reader.isEndDocument()) {
            break;
        }

        if (reader.isStartElement())
        {
            QStringRef elementName = reader.name();
            if (elementName == "project") {
                QXmlStreamAttributes attrs = reader.attributes();
                currentProjectId = attrs.value("identifier").toString();
            }
            else if (elementName == "path") {
                pathByProjectId[currentProjectId] = reader.readElementText(QXmlStreamReader::IncludeChildElements);
            }

            continue;
        }
    }

    for(auto it = pathByProjectId.constBegin(),
        end = pathByProjectId.constEnd(); it != end; ++it)
    {
        qDebug() << "Path for project " << it.key() << ": " << it.value();
    }

    file.close();

    return 0;
}

这是我提供给这个示例程序的稍微修改的示例:

<?xml version="1.0" encoding="UTF-8"?>
<body>
<project identifier="project1">
    <author>Joe Smith</author>
    <author2>Rick Jones</author2>
    <path>projects/internal/project1</path>
    <version>1.51</version>
</project>
<project identifier="project2">
     <author>Terry Chimes</author>
     <author>Janie Jones</author>
     <path>projects/external/project2</path>
     <version>19.77</version>
 </project>
 </body>

我在您的示例中添加的是 XML 版本/编码声明 + 高级body标记,以防止QXmlStreamReader认为第一个project标记是整个文档的根元素。我还更改了第一个项目的路径,使其与第二个项目的路径不同。

这是我得到的输出:

Path for project  "project1" :  "projects/internal/project1"
Path for project  "project2" :  "projects/external/project2"
于 2018-04-24T07:49:45.087 回答