Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt] QXmlStreamReader и функция clear()


Автор: null56 15.5.2009, 14:19
Хотел поинтересовать такой вещью...
Я создаю объект парсера и хочу его использовать несколько раз, но без уничтожения, то есть используя перегруженную функцию parse()
Код

inline bool XmlParser :: parse(const QByteArray & rXml)
{
    if (rXml.isEmpty()) { return false; }
    clear();
    addData(rXml);
    while (!atEnd())
    {
        switch (readNext())
        {
            case(StartElement): { ... break; }
            case(EndDocument): { ... break; }
            case(Characters): {... break; }
            default: break;
        }
    }
    if (hasError())
        { qDebug("Error message: %s", errorString().toStdString().c_str()); return false; }
    return true;
}

Все хорошо работает, пока у меня не появляются ошибки Xml, либо мои, либо стандарта, не важно... суть в том, что когда я пытаюсь использовать снова этот парсер, у меня данные предыдущие не очищаются, и парсить этим объектом не получается, хотя я как видите постоянно перед добавлением новых данных вызываю функцию clear().

Что я делаю не правильно и верно ли я использую эту функцию...
Заранее благодарен за помощь

Автор: null56 21.5.2009, 22:34
Ребята неужели парсер одноразовый, я не понимаю... вот тут кое что нашел по своей проблеме, не могли бы вы объяснить, что имели в виду троли описывая это...
Цитата

TokenType QXmlStreamReader::readNext ()

Reads the next token and returns its type.

If an error() has been reported, reading is no longer possible. In this case, atEnd() always returns true, and this function will do nothing but return Invalid.

The one exception to this rule are errors of type PrematureEndOfDocumentError. Subsequent calls to atEnd() and readNext() will resume this error type and try to read from the device again. This iterative parsing approach makes sense if you can't or don't want to read the entire data in one go, for example, if it is huge, or it is being delivered over a network connection


я набросал простой пример, который выдает это же узкое место
xmlparser.h
Код

class XmlParser : public QXmlStreamReader
{
public:
    XmlParser();
    bool parse(const QByteArray & rXml);
    void onStartElement(const QString & rName);
    void onEndDocument();
};

xmlparser.cpp
Код

#include "xmlparser.h"

XmlParser::XmlParser()
{
}

bool XmlParser :: parse(const QByteArray & rXml)
{
        clear();
        addData(rXml);
        while (!atEnd())
        {
                switch (readNext())
                {
                case(StartElement): { onStartElement(name().toString()); break; }
                case(EndDocument): { onEndDocument(); break; }
                default: {}
                }
        }
        if (hasError())
            { qDebug("Error message: %s", errorString().toStdString().c_str()); }
        return true;
}

void XmlParser :: onStartElement(const QString & rName)
{
    if (rName == "preved")
        { qDebug("my raise"); raiseError("custom error"); }
}

void XmlParser :: onEndDocument()
{
    qDebug("On end document");
}

main.cpp
Код

#include <QtCore/QCoreApplication>
#include "xmlparser.h"
int main(int argc, char *argv[])
{
    XmlParser parse;
    parse.parse("<preved></preved>");
    parse.parse("<preved1></preved1>");
    return 0;
}

Задача примера, встретив тег с именем "preved" сгенерить ошибку "custom error", что он успешно и делает, но вот почему вводя правильные, для данного примера, входные данные во втором вызове метода parse происходит вылет с ошибкой PrematureEndOfDocumentError. глосащем о том, что нарушена структура, вот в этом вопрос.
Правильно ли я использую данный парсер и почему происходит ошибка именно после того, как я генерю raiseError?

ЗЫ: замечу, что изменив первые данные на другую пару тегов, оба процесса отработают

Заранее благодарен за помощь всем откликнувшимся

Автор: SABROG 22.5.2009, 09:15
Цитата(null56 @  21.5.2009,  22:34 Найти цитируемый пост)
что имели в виду троли описывая это...

Если возникает ошибка, то дальнейшее чтение невозможно, функция atEnd() возвращает true и метод readNext() ничего не делает, но возвращает токен типа QXmlStreamReader::Invalid.

Но есть одно исключение из этого правила. Ошибка типа QXmlStreamReader::PrematureEndOfDocumentError говорит о том, что был отпарсен кусок xml'я правильной структуры (например <preved>text</preved>, а не <preved>text<pr). И устройство ожидает получение следующего куска xml'я, который может качаться через интернет например. Как только кусок скачается его надо добавлять через метод addData и тогда парсинг можно возобновлять. С конструктором QXmlStreamReader::QXmlStreamReader ( QIODevice * device ) это естественно работать не будет.

Автор: null56 22.5.2009, 15:43
ну а я что делаю???
Код

        clear();
        addData(rXml);


я очищаю старый контекст(clear), когда вызывается функция parse и добавляю новые данные, которые хочу распарсить с нуля (addData), данные передавались в качестве аргумента, почему выскакивает ошибка??? ведь последовательность вроде правильная parse -> clear -> addData, что ему не нравится? я не понимаю?

Автор: SABROG 22.5.2009, 16:23
Цитата(null56 @  22.5.2009,  15:43 Найти цитируемый пост)
ну а я что делаю???

Ты просил перевести, я перевел.

Попробуй унаследоваться от QXmlSimpleReader.

Автор: null56 22.5.2009, 20:12
SABROG, спасибо большое, это я так сам с собой разговариваю... просто не могу понять, что не получается

Автор: null56 23.5.2009, 23:30
видимо не один я такой, возможно бага, которая уже решена
http://www.qtsoftware.com/developer/task-tracker/index_html?method=entry&id=170748

Добавлено через 1 минуту и 6 секунд
http://www.qtsoftware.com/developer/task-tracker/index_html?method=entry&id=179320

Автор: null56 26.5.2009, 11:33
Так и есть...
Поставил версию Qt 4,5, парсер работает как надо

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)