QXmlStreamReader и большое количество уровней |
Здравствуйте, гость ( Вход | Регистрация )
QXmlStreamReader и большое количество уровней |
SABROG |
13.7.2009, 14:50
Сообщение
#1
|
Профессионал Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: 34 |
Решил попробовать класс QXmlStreamReader. Изучив пример streambookmarks я реализовал свой парсер. И вот что мне не понравилось. Можно написать простенький код, который будет сравнивать каждое название ключа на токен isStartElement с нужным нам. Недостаток такого метода - большое количество операций сравнений и падение скорости. Зато очень просто, когда ключи имеют уникальные имена, не нужно контролировать вложенность, родительские отношения. Второй вариант (правильный). На каждый уровень дерева выделяется отдельный метод с while(!atEnd()). Подобное выделение требует создание нового метода для каждого такого уровня. Если глубина дерева в xml'e большая, то можно себе представить какое огромное количество методов получится! Например у меня глубина дерева такая:
Т.е. 9 методов (на каждый уровень) и в каждом по циклу while(). При этом меня совершенно не интересуют промежуточные уровни, только последние. Теперь сижу и думаю может сделать какие-нибудь указатели на методы, которые будут вызываться по очереди на одном while. Скажем QQueue/QHash с указателем на метод и строкой сравнения. --- Только вот на самом деле там даже больше 9и методов получится, т.к. в xml'е еще другие блоки есть, такой например:
Сообщение отредактировал SABROG - 13.7.2009, 14:59 |
|
|
ViGOur |
13.7.2009, 15:56
Сообщение
#2
|
Мастер Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: 40 |
Код в студию, можно занятся оптимизаторством и универсальностью кода.
|
|
|
SABROG |
13.7.2009, 17:45
Сообщение
#3
|
Профессионал Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: 34 |
Код в студию, можно занятся оптимизаторством и универсальностью кода. Давайте попробуем, коль не боитесь Вот простой вариант:
Недостаток в том, что нет разбора кому какой ключ принадлежит. Т.е. если в xml'e будет 3 ветки и в каждой подветке будут ключи с одинаковыми именами, то я не смогу разобрать ключи "по кучкам". А есть такая махина:
Соответственно тут и так всё понятно. Плюс в том, что тут я точно знаю какой ветке что принадлежит. По скорости и первый и второй варианты почти одинаковы. XML файл на 5,5Мб парсится ~297ms. Сообщение отредактировал SABROG - 13.7.2009, 18:21 |
|
|
ViGOur |
13.7.2009, 19:29
Сообщение
#4
|
Мастер Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: 40 |
Жесть!
А почему нельзя сделать рекурсию с созданием дерева наследников? Меньше копи/паста одного и того же кода. |
|
|
SABROG |
13.7.2009, 20:28
Сообщение
#5
|
Профессионал Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: 34 |
А почему нельзя сделать рекурсию с созданием дерева наследников? Я об этом думал пока ехал домой. Завтра попробую сделать рекурсию, но без дерева наследника. Попробую передавать в рекурсивную функцию нужные мне ключи и уже фильтровать их через if (name() == parName). |
|
|
SABROG |
14.7.2009, 14:25
Сообщение
#6
|
Профессионал Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: 34 |
Да уж, что-то не очень получается. Если делать рекурсию без дерева наследников, то получается каждый ключ сравнивается со всем списком ключей снова, это замедляет парсинг. Есть мысль сделать дерево наследников таким образом: "tourml/sources/source/packets/packet/packetheader/spo/dates/date" + QStringList list = str.split("/");
Затем в рекурсии проходить по элементам списка и удалять из него пройденные ключи. Но этот вариант мне кажется каким-то странным, слабеньким вариантом XPath. --- Так, теперь я узнал, что есть разные варианты парсеров: DOM, SAX, StAX. Причем QXmlStreamReader это StAX парсер, который по сути вырос из Pull парсера. StAX и SAX совершенно разные вещи, первый не использует callback функции в отличие от второго. Сообщение отредактировал SABROG - 14.7.2009, 21:25 |
|
|
SABROG |
14.7.2009, 22:40
Сообщение
#7
|
Профессионал Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: 34 |
В общем посмотрел я десяток примеров использования StAX парсера на Java и пришел к выводу, что это, в принципе, нормальный код. В основном, как я и говорил люди выносят циклы while() в отдельные методы и жестко вызывают метод nextTag() (которого кстати нет в Qt, а он пропускает комментарии всё остальное, что не является tag'ом), который устанавливает курсор на следующий элемент, подразумевая тема самым, что если сначала шел Tag = "Name", то за ним обязательно должен идти Tag = "Surname". Т.е. надеются на жесткий порядок следования tag'ов, чтобы уменьшить количество итераций через while(). Тем не менее почти везде такие здоровые портянки. Нигде не обнаружил рекурсии или какой-то специальной оптимизации.
Сообщение отредактировал SABROG - 14.7.2009, 23:06 |
|
|
ViGOur |
15.7.2009, 10:32
Сообщение
#8
|
Мастер Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: 40 |
Ты немного не понял, рекурсия c примерно таким условием:
общая идею думаю должна быть понятна. если не понятно, постараюсь описать подробней. Сообщение отредактировал ViGOur - 15.7.2009, 10:37 |
|
|
SABROG |
15.7.2009, 11:14
Сообщение
#9
|
Профессионал Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: 34 |
Да оно всё это понятно, я тоже об этом говорю. Сам подход странный с точки зрения стиля программирования. Это получается некий гибрид Pull и Push парсера. Просто в таком случае тогда проще взять обычный SAX2 (push) парсер - QXmlReader. Но он не поддерживает потоковые данные и не умеет писать xml'и. Да и заполнять надо как-то этот вектор хитро. Например на одну ветку может приходится несколько нужных подветок, тогда придется дублировать имена основной ветки по количеству необходимых дочерних узлов. Или отказываться от вектора и сделать через дерево указателей. Опять же, такое дерево должно отражать некий путь парсинга. Насколько будет удобно изменять этот путь, подстраиваясь под новые форматы xml'ей? А мне надо в итоге написать 4 xml парсера. В принципе как я говорил выше, можно сделать некий аналог XPath'а, распарсить строчки с нужными путями в дерево. Правда в итоге получится новый оверхед. Тут выбор стоит, либо красивый и компактный код, но в жертву приносится скорость парсинга. Либо увеличение размера приложения из-за копи-пастинга и отвратительный код с точки зрения стиля программирования, но шустрый парсер.
|
|
|
ViGOur |
15.7.2009, 12:24
Сообщение
#10
|
Мастер Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: 40 |
Так в том то и дело, что в твоем случае как я понял идут уникальные имена подветок и соответственно не нужно отслеживать, а если нужно наследовать, то достаточно ввести еще один параметр в массив:
и все так же с вектором, а так как родитель в вектор попадет раньше дочки, то и указатель на родителя будет и при изменении расположения элементов и их родителей никаких проблем с изменением и никакой путаницы.Вплоть до того, что ты сам программно сможешь менять значения, положения элементов и их родителей, а потом сохранять. Только в структуру нужно будет еще несколько аргументов ввести. |
|
|
Текстовая версия | Сейчас: 26.12.2024, 19:53 |