在 StartElement (QXmlStreamReader) 中读取 XML 个标签
Read XML tags inside StartElement (QXmlStreamReader)
因此,我正在尝试通读一份中等大小的 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 的 QXmlStreamReader
,它可能是由虐待狂创建(或记录)的。
我可以通过使用 xmlReader.readNextStartElement
找到每个 project
- 或者逐个读取标签,直到我找到一个具有内部属性的标签(只有 project
标签在这个文件中有属性).
但是当我读到其中一个父元素时,QXmlStreamReader
吸收了每个标签,直到它的结束 </project>
标签。问题是我需要获取其中一些数据,在本例中,是 <path></path>
标签内的内容。
我可以用 xmlReader.readElementText(QXmlStreamReader::IncludeChildElements
检索所有被吞噬的数据,但这只是一个没有标签的大数据转储。
有谁知道我如何 "rewind" 和阅读内部标签?还是阻止流 reader 向前倾斜并吸收所有数据?
最可能的解释是你做错了什么,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 version/encoding 声明+ 高级body
标记以防止QXmlStreamReader
认为第一个project
标记是整个文档的根元素。我还更改了第一个项目的路径,使其与第二个项目的不同。
这是我得到的输出:
Path for project "project1" : "projects/internal/project1"
Path for project "project2" : "projects/external/project2"
因此,我正在尝试通读一份中等大小的 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 的 QXmlStreamReader
,它可能是由虐待狂创建(或记录)的。
我可以通过使用 xmlReader.readNextStartElement
找到每个 project
- 或者逐个读取标签,直到我找到一个具有内部属性的标签(只有 project
标签在这个文件中有属性).
但是当我读到其中一个父元素时,QXmlStreamReader
吸收了每个标签,直到它的结束 </project>
标签。问题是我需要获取其中一些数据,在本例中,是 <path></path>
标签内的内容。
我可以用 xmlReader.readElementText(QXmlStreamReader::IncludeChildElements
检索所有被吞噬的数据,但这只是一个没有标签的大数据转储。
有谁知道我如何 "rewind" 和阅读内部标签?还是阻止流 reader 向前倾斜并吸收所有数据?
最可能的解释是你做错了什么,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 version/encoding 声明+ 高级body
标记以防止QXmlStreamReader
认为第一个project
标记是整个文档的根元素。我还更改了第一个项目的路径,使其与第二个项目的不同。
这是我得到的输出:
Path for project "project1" : "projects/internal/project1"
Path for project "project2" : "projects/external/project2"