crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

> QXmlStreamReader и большое количество уровней
SABROG
  опции профиля:
сообщение 13.7.2009, 14:50
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Решил попробовать класс QXmlStreamReader. Изучив пример streambookmarks я реализовал свой парсер. И вот что мне не понравилось. Можно написать простенький код, который будет сравнивать каждое название ключа на токен isStartElement с нужным нам. Недостаток такого метода - большое количество операций сравнений и падение скорости. Зато очень просто, когда ключи имеют уникальные имена, не нужно контролировать вложенность, родительские отношения. Второй вариант (правильный). На каждый уровень дерева выделяется отдельный метод с while(!atEnd()). Подобное выделение требует создание нового метода для каждого такого уровня. Если глубина дерева в xml'e большая, то можно себе представить какое огромное количество методов получится! Например у меня глубина дерева такая:

tourml/sources/source/packets/packet/packetheader/spo/dates/date


Т.е. 9 методов (на каждый уровень) и в каждом по циклу while(). При этом меня совершенно не интересуют промежуточные уровни, только последние.

Теперь сижу и думаю может сделать какие-нибудь указатели на методы, которые будут вызываться по очереди на одном while. Скажем QQueue/QHash с указателем на метод и строкой сравнения.
---
Только вот на самом деле там даже больше 9и методов получится, т.к. в xml'е еще другие блоки есть, такой например:

tourml/references/tourtypes/tourtype


Сообщение отредактировал SABROG - 13.7.2009, 14:59
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
 
Начать новую тему
Ответов
SABROG
  опции профиля:
сообщение 22.7.2009, 15:33
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Нашел забавную статью про StAX, пример рассматривается на Java и XmlStreamReader.
Забавно в ней то каким образом они решают проблему здоровых циклов while(). Смысл следующий. Создается абстрактный базовый класс типа ComponentParser. Есть 2 ключа "author" и "entry", при вхождении в эти ключи должен вызываться свой парсер. Поэтому на эти ключи создается 2 класса AuthorParser и EntryParser, оба на базе ComponentParser. Создается map (типа QMap) - {"ИмяКлюча":ОбъектНаБазеComponentParser}. Уже начинает напоминать наши callback'и. Внутри каждого такого ComponentParser'а также есть свой map для дочерних узлов. Вызов метода парсинга для ключа выглядит так:

if (delegates.containsKey(element)) {
            ComponentParser parser = (ComponentParser) delegates.get(element);
            parser.parse(staxXmlReader);
          }


delegates - наш map, parser - объект, который отвечает за парсинг конкретного ключа.

На мой взгляд это мало чем отличается от этого:

void Tag1()
{
    while(!atEnd) {
        ...
    }
}

void Tag2()
{
    while(!atEnd) {
        ...
    }
}

void Tag3()
{
    while(!atEnd) {
        ...
    }
}

void Tag4()
{
    while(!atEnd) {
        ...
    }
}


Просто они взяли "детский" пример (глубина дерева 1 уровень) xml'я, да еще умудрились наворотить всего вокруг него, а циклы while() заменили на StaxUtil.moveReaderToElement("name",staxXmlReader);, по сути одно и тоже что и это:

void moveReaderToElement(const QString &name)
{
    while(!atEnd) {
        ...
        if (startElement == name)
        break;
    }
}
.

В моем предыдущем варианте я использовал свой метод readNext(), который пропускал энное количество ключей. В этой статье предпочитают не пропускать ключи, а искать нужный. Минус в том, что это дополнительные операции сравнения строк имен на каждом ключе. Плюс в том, что код выглядит не уродско. Снова надо делать выбор, либо красота кода, либо скорость парсинга.
Таким образом выходит, что для удобной работы в классе QXmlStreamReader не хватает методов типа: nextTag, nextTag("name"), skipSubTree() и возможности работать асинхронно в цикле событий как QNetworkAccessManager, или потокового варианта QXmlStreamReaderThreaded. Дело в том, что если устройство установлено через setDevice, то парсер не увидит новых приходящих данных, скажем по сокету пока у парсера не будет возможности дать отработать циклу событий. QEventLoop хоть и работает, но это имхо костыль. Интерфейс программы размораживается при таком раскладе, значит нужен модальный диалог. Также встает вопрос о прерывании парсинга. Это все таки цикл, значит надо каким-то образом дать знать парсеру, что пора выходить.
---
Кстати в статье упоминается метод parseElement, на самом деле это опечатка, в исходниках метод parse(). Еще нашел в исходниках реализацию метода moveReaderToElement:

  public static void moveReaderToElement(String target, XMLStreamReader reader) throws XMLStreamException {

    // If current element is equal to target

    String readElement = null;
    for (int event = reader.next(); event != XMLStreamConstants.END_DOCUMENT; event = reader.next()) {

      if ((event == XMLStreamConstants.START_ELEMENT) && (reader.getLocalName().equals(target))) {
        return;
      }
    }
  }


Он хорош только для ключей в одном экземпляре. Если в xml файле будут списки типа:

<name>Витя</name>
<name>Петя</name>
<name>Вася</name>
<name>Коля</name>


То нужен цикл while() и проверка на выход из поддерева иначе парсер поползет дальше по всему xml'ю до самого конца. К сожалению, как я уже говорил, пример в статье слабый, хотя и пишется, что ориентирован он на серьезные xml'и. Продумали не все.

Сообщение отредактировал SABROG - 23.7.2009, 15:16
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Сообщений в этой теме
- SABROG   QXmlStreamReader и большое количество уровней   13.7.2009, 14:50
- - ViGOur   Код в студию, можно занятся оптимизаторством и уни...   13.7.2009, 15:56
|- - SABROG   Цитата(ViGOur @ 13.7.2009, 16:56) Код в с...   13.7.2009, 17:45
- - ViGOur   Жесть! А почему нельзя сделать рекурсию с соз...   13.7.2009, 19:29
- - SABROG   Цитата(ViGOur @ 13.7.2009, 20:29) А почем...   13.7.2009, 20:28
- - SABROG   Да уж, что-то не очень получается. Если делать рек...   14.7.2009, 14:25
- - SABROG   В общем посмотрел я десяток примеров использования...   14.7.2009, 22:40
- - ViGOur   Ты немного не понял, рекурсия c примерно таким усл...   15.7.2009, 10:32
- - SABROG   Да оно всё это понятно, я тоже об этом говорю. Сам...   15.7.2009, 11:14
- - ViGOur   Так в том то и дело, что в твоем случае как я поня...   15.7.2009, 12:24
- - Tonal   То, что тут пытаетесь изобразить, называется конеч...   15.7.2009, 12:38
- - SABROG   Как я и писал выше затык будет в заполнении таблиц...   15.7.2009, 13:16
- - SABROG   Такой вопрос насчет QXmlStreamReader::PrematureEnd...   15.7.2009, 21:35
- - SABROG   Нашел забавную статью про StAX, пример рассматрива...   22.7.2009, 15:33
- - SABROG   Сегодня заметил статью в блоге на QtSoftware и о т...   24.7.2009, 13:27
- - Litkevich Yuriy   Цитата(SABROG @ 24.7.2009, 17:27) я немно...   24.7.2009, 13:39
- - SABROG   В общем я немного заморочился на эту тему и напи...   29.8.2009, 14:40


Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 18.4.2024, 15:07