Qt QXmlStreamReader访问冲突

时间:2018-08-23 05:35:48

标签: c++ xml qt qxmlstreamreader

我正在使用Qt 5.11.1(MSVSC2015 32bit)和QtCreator 4.6.2。 我无法使用QXmlStreamReader解析XML。代码基于Qt's example编写。 执行我的代码时,它会在checkWarnMessage函数的QIODevice.cpp中产生访问冲突。 image显示呼叫堆栈和发生访问冲突的确切行。

实际的XML i更复杂,并且具有嵌套元素。解析XML的函数的实现方式与Qt示例中的void XbelReader :: readXBEL()函数的实现方式相同(基于元素名称,调用了适当的函数来解析该元素)。但是通过这个简单的示例,我设法重现了实际解决方案中遇到的问题。

XML是:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <element1>1</element1>
    <element2>2</element2>
    <element3>3</element3>
    <element4>4</element4>
    <element5>5</element5>
    <element6>6</element6>
</root>

解析此XML的代码为:

#include <string>
#include <stdexcept>
#include <iostream>

#include <QCoreApplication>
#include <QXmlStreamReader>
#include <QFile>
#include <QString>

#define ASSERT_ELEMENT_NAME(NAME) Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == NAME);

using namespace std;

void OpenFile(const QString& fileName, QXmlStreamReader& xmlReader)
{
    QFile configFile(fileName);
    if (configFile.open(QFile::ReadOnly | QFile::Text) == false)
        throw runtime_error(string("Failed to open file: ") + configFile.errorString().toStdString());

    xmlReader.setDevice(&configFile);
    if (xmlReader.readNextStartElement() == false)
        throw runtime_error("File does not have root element");

    if (xmlReader.name() != "root")
        throw runtime_error("File has invalid root element");
}

void ParseElement1(QXmlStreamReader& xmlReader)
{
    ASSERT_ELEMENT_NAME("element1");

    auto text = xmlReader.readElementText().trimmed();
    auto isOk = false;
    auto value = text.toInt(&isOk);

    if (isOk == false)
        throw runtime_error(string("invalid value: ") + text.toStdString());
    else
        cout << "element1: " << value << endl;
}

void ParseElement2(QXmlStreamReader& xmlReader)
{
    ASSERT_ELEMENT_NAME("element2");

    auto text = xmlReader.readElementText().trimmed();
    auto isOk = false;
    auto value = text.toInt(&isOk);

    if (isOk == false)
        throw runtime_error(string("invalid value: ") + text.toStdString());
    else
        cout << "element2: " << value << endl;
}

int main()
{
    QXmlStreamReader xmlReader;

    OpenFile("config.xml", xmlReader);

    while(xmlReader.readNextStartElement())
    {
        if(xmlReader.name() == "element1")
            ParseElement1(xmlReader);
        if(xmlReader.name() == "element2")
            ParseElement2(xmlReader);
        else
            xmlReader.skipCurrentElement();
    }
}

如果我在主函数中注释了两行:

        if(xmlReader.name() == "element2")
            ParseElement2(xmlReader);

不会发生访问冲突。

我真的不知道我在做什么错。还是QXmlStreamReader中存在错误?我认为,即使我做错了什么,也不应在Qt的库中发生访问冲突。

可以从此link

下载整个项目(XmlParser.pro,main.cpp和config.xml)。

编辑

我已按照曼森(Manthan)的建议修正了自己的例子,该例子按预期工作。我向XML添加了另一件事。我在element1之前添加了大的多行注释。注释本身有8019个字符,包括空格字符,而整个XML文件有8266个字符。

XML现在看起来像

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <!--
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment,
    comment, comment, co
    -->
    <element1>1</element1>
    <element2>2</element2>
    <element3>3</element3>
    <element4>4</element4>
    <element5>5</element5>
    <element6>6</element6>
</root>

我已经使用XML Tools插件在Notepad ++中以及xmlvalidation.xml上检查了XML是否有效。当我使用新的XML执行固定的示例时,再次在先前链接的图像上所描绘的完全相同的地方出现访问冲突。

现在,如果我从XML的注释中删除最后一个“ o”字符(或从注释中删除任何其他字符,或者例如从element6的文本中删除“ 6”,或者事实上从XML中的任何字符保持XML有效) ,示例成功执行。这是我最初的问题。我的原始XML文件中有很多注释,导致文件大于8KB。目前,作为一种解决方法,我删除了注释以避免访问冲突。

我不清楚注释(或文件)长度如何导致访问冲突。

可以从此link

下载整个项目

1 个答案:

答案 0 :(得分:4)

问题在while循环内。如下更新。

while(xmlReader.readNextStartElement())
{
    if(xmlReader.name() == "element1")
        ParseElement1(xmlReader);
    else if(xmlReader.name() == "element2")
        ParseElement2(xmlReader);
    else
        xmlReader.skipCurrentElement();
}

在您的代码中,第一个元素的类型为'element1',然后首先对其进行处理(使用第一个if),然后它们再次到达else,在此处尝试跳过该元素,从而导致问题。