Название: [решено] Чтение XML, запись XML Отправлено: sergek от Январь 06, 2010, 17:10 Коллеги!
Подскажите, пожалуйста, правильно ли я понял - при чтении и обработке содержимого xml-файлов большого размера (сотни кбайт - десятки Мбайт) средствами Qt следует использовать QXmlSimpleReader, для записи результатов в xml-файл - QXmlStreamWriter? DOM прошу не предлагать, не подходит. С SAX понятно - для чтения, а вот примеров создания xml-файлов нашел немного. Особенно порадовал SAX Bookmarks Example :( Спасибо. Название: Re: Чтение XML, запись XML Отправлено: Akaiten от Январь 15, 2010, 15:46 Для чтения использую QXmlStreamReader, для создания QXmlStreamWriter. А что с созданием непонятно? это ж проще пареной репы. Например
Код
Должно получиться что то вроде этого Код
Добавлено 18.01.2010 11:14: Забыл закрывающий тег для <img> :) Название: Re: Чтение XML, запись XML Отправлено: Marat(Qt) от Январь 16, 2010, 16:29 Должно получиться что то вроде этого Тэг img не закрытКод
Название: Re: Чтение XML, запись XML Отправлено: Resager от Январь 16, 2010, 22:02 Тэг img не нуждается в закрытии, однако по стандарту XHTML 1.0 нужно дописывать (для такого типа тэгов) в конце "/"
Как то: <img src="image.jpg" alt="image" /> (читать здесь http://stepbystep.htmlbook.ru/?id=63) Неужели там это непридусмотрено? :( Мне как раз понадобится работа с XML файлами... не подскажете ли (пару примерчиков) чтения XML-файла? Меня особенно интересует, можно ли "добавлять" в XML, в середину, текст большей размерности (буду использовать по прототипу БД, для хранения многострочных текстовых данных), не использую нормальные БД по причине того. что поле ограниченной длины. Например было: Код
Стало: Код ( Ну и конечно чтобы это быстро было. Название: Re: Чтение XML, запись XML Отправлено: Marat(Qt) от Январь 16, 2010, 23:09 Если положите это в value=... (т.е. в атрибут), то наткнетесь на ту же проблему что и в соседнем топике http://www.prog.org.ru/topic_11648_0.html (http://www.prog.org.ru/topic_11648_0.html)
Если будете активно DOM использовать - то вся база будет в ОЗУ лежать, а так вполне ничего. Жить можно будет. Название: Re: Чтение XML, запись XML Отправлено: Resager от Январь 17, 2010, 13:02 Есть хорошие примеры для работы с DOM? Это хорошо, с одной стороны, что хранится будет в ОЗУ, и быстро, и как вы говорите проблем меньше, а если мне не охота нагружать ОЗУ этив файлом, ибо предпологается большой размер файла (~100 мб максимум). Думаю надо проверить на быстродействие оба варианта, и если видимого отличия не будет, тогда лучше не занимать память.
Класть мне всё равно куда, хотя в "KEY", хоть вообще между тэгами (ибо придётся как уже говорил как то многострочные текстовые блоки хранить). Так сможете подсказать? З.Ы. В примере выше не показано, как например подключать файл, если не сложно. покажите?! Название: Re: Чтение XML, запись XML Отправлено: sergek от Январь 17, 2010, 14:30 Для чтения использую QXmlStreamReader, для создания QXmlStreamWriter. А что с созданием непонятно? это ж проще пареной репы. Например Я бы не назвал это пареной репой :) Однако ход мысли понятен, спасибо. Предстоит много нудной и противной работы :(Код
Название: Re: Чтение XML, запись XML Отправлено: Marat(Qt) от Январь 17, 2010, 15:11 Есть хорошие примеры для работы с DOM? Это хорошо, с одной стороны, что хранится будет в ОЗУ, и быстро, и как вы говорите проблем меньше, а если мне не охота нагружать ОЗУ этив файлом, ибо предпологается большой размер файла (~100 мб максимум). Думаю надо проверить на быстродействие оба варианта, и если видимого отличия не будет, тогда лучше не занимать память. У xml есть язык запросов - XQuery, не знаю как он для вставки (по сути должны быть средства) но вот для чтения очень даже. Составляете запрос и получаете конкретную строку или набор строк, удовлетворяющих запросу. Класть мне всё равно куда, хотя в "KEY", хоть вообще между тэгами (ибо придётся как уже говорил как то многострочные текстовые блоки хранить). Так сможете подсказать? Название: Re: Чтение XML, запись XML Отправлено: Akaiten от Январь 18, 2010, 11:19 Меня особенно интересует, можно ли "добавлять" в XML, в середину, текст большей размерности ... Ну и конечно чтобы это быстро было. Обычно, чтобы изменить XML файлик требуеться его полностью прочитать (и обычно распарсить) в память. Название: Re: Чтение XML, запись XML Отправлено: Resager от Январь 18, 2010, 16:29 Обычно, чтобы изменить XML файлик требуеться его полностью прочитать (и обычно распарсить) в память. Ну это логично, по другому думаю никак, даже текстовый файл...Как происходит загрузка в память XML-файла и его парсинг, что для этого есть в QT? Название: Re: Чтение XML, запись XML Отправлено: Marat(Qt) от Январь 18, 2010, 16:50 Обычно, чтобы изменить XML файлик требуеться его полностью прочитать (и обычно распарсить) в память. Ну это логично, по другому думаю никак, даже текстовый файл...Как происходит загрузка в память XML-файла и его парсинг, что для этого есть в QT? Название: Re: Чтение XML, запись XML Отправлено: Akaiten от Январь 18, 2010, 17:03 Обычно, чтобы изменить XML файлик требуеться его полностью прочитать (и обычно распарсить) в память. Ну это логично, по другому думаю никак, даже текстовый файл...Как происходит загрузка в память XML-файла и его парсинг, что для этого есть в QT? Могу ещё раз написать, что я, например, использую QXmlStreamReader. Если структура XML довольна проста, то при помощи QXmlStreamReader его можно просто и быстро распарсить. В качестве примера смотри Qt\tools\linguist\shared\ts.cpp - парсер TS-файлов. Также для чтения можно использовать QXmlSimpleReader (ни разу не использовал) или QDomDocument. Название: Re: Чтение XML, запись XML Отправлено: SABROG от Январь 21, 2010, 10:12 QXmlStreamReader это StAX, по сути может работать с любым объемом, на его основе можно построить сетевой протокол на базе xml запросов и ответов. Т.е. ему всё равно какого размера файл, он будет работать. Из недостатков - только для чтения, только forward cursor, т.е. нельзя вернуться в предыдущую ноду и посмотреть чего там было, код парсера получается некрасивым, не понятным, много оверхеда (повторяющегося кода). Зато хорошо работает.
Название: con: Чтение XML, запись XML Отправлено: sergek от Январь 28, 2010, 22:07 Коллеги, в продолжение темы.
При записи с помощью QXmlStreamWriter xml-документа нужно, чтобы в декларацию xml записывалась кодировка, типа <?xml version="1.0" encoding="WINDOWS-1251"?>. Курю assistant, в котором говорится что при использовании QXmlStreamWriter::setCodec ( QTextCodec * codec ) the encoding information is stored in the initial xml tag. Главное, чтобы вызов this function был before calling writeStartDocument(). Пишу QXmlStreamWriter writer; writer.setCodec("WINDOWS-1251"); writer.writeStartDocument(); Фигвам. В созданном документе декларация выглядит как <?xml version="1.0"?> без encoding. Думал, что кодек кривой, так нет - если сделать QTextCodec * c=writer.codec(); QString sc=c->name(); то sc показывает правильно: windows-1251. Пробовал разную кодировку, в том числе UTF, все едино... Подскажите, как правильно сформировать декларацию в прологе? Гуру, ау!!! Название: Re: Чтение XML, запись XML Отправлено: BRE от Январь 28, 2010, 22:28 Попробуй воспользоваться этим:
void QXmlStreamWriter::writeProcessingInstruction ( const QString & target, const QString & data = QString() ) Название: Re: Чтение XML, запись XML Отправлено: Akaiten от Январь 29, 2010, 09:46 Encoding записывается только в случае, если QXmlStreamWriter пишет в QIODevice.
Название: Re: Чтение XML, запись XML Отправлено: SABROG от Январь 29, 2010, 14:11 Создаю xml через QXmlStreamWriter, в качестве устройства передаю QByteArray (он не QIODevice). Без явной установки кодировки получаю "UTF-8", при Windows-1251:
Код
Получаю в xml - "Windows-1251". Qt 4.6.1. Всё работает. Название: Re: Чтение XML, запись XML Отправлено: sergek от Январь 29, 2010, 20:51 Цитировать Encoding записывается только в случае, если QXmlStreamWriter пишет в QIODevice Цитировать Создаю xml через QXmlStreamWriter, в качестве устройства передаю QByteArray (он не QIODevice) Вот где собака порылась! Из трех конструкторов QXmlStreamWriter с параметрами QIODevice, QByteArray и QString я выбрал тот, который мне был понятнее (последний). А он-то и работает кривовато. Просто заменил строку Код: QString outXml; на Код: QByteArray outXml; и что хотел, получил. Спасибо! Название: Re: Чтение XML, запись XML Отправлено: warlock от Февраль 08, 2010, 00:42 Возможно ли обновлять xml файл без полной его перезаписи? Т.е. обновить какуето запись?
Название: Re: Чтение XML, запись XML Отправлено: sergek от Февраль 25, 2010, 21:21 Коллеги, еще вопрос, если позволите.
Нет ли какой-нибудь особенности преобразования прописной русской буквы "И" из UTF-8 с помощью QTextCodec? Проблема следующая. Имеется файл примерно такой (скопировано из QTextEdit): Код: <?xml version="1.0" encoding="UTF-8"?> Я его загружаю с помощью QTextStream с отключенным автоопределением кодировки, затем перекодирую в Unicode с использованием кодека QTextCodec::codecForName("UTF-8"). Получаю Код: <?xml version="1.0" encoding="UTF-8"?> Если читать этот же файл с использованием QXmlSimpleReader, то значение атрибута передается правильно: Код: Acc="11111ИИ1111111111111" Кодеки ForTr, ForLocale, ForCStrings установлены в "windows-1251". Такое ощущение, что я что-то не понимаю (и не только я - топики с кодировками тут обширные, я их полистал). На всякий случай, некоторые куски кода: Код: QTextCodec *cp1251 = QTextCodec::codecForName("windows-1251"); Название: Re: Чтение XML, запись XML Отправлено: SABROG от Февраль 26, 2010, 03:05 Код
Что вижу я из этого кода. Ставим локаль в cp1251, открываем поток, который берет текущий кодек локали (cp1251) и отключаем определение кодировок UTF-16 и UTF-32 через BOM (который не добавляют большинство текстовых редакторов). В строчке с stream.readAll() в text текст попадает уже в юникоде. cp1251->Unicode 4.0 Затем мы берем строку text (которая у нас уже в Unicode 4.0) и добавляем в QByteArray. Выбираем кодек UTF-8 и ...: выполняем преобразование Unicode 4.0 в Unicode 4.0, обманывая кодек, сказав ему, что у нас там UTF-8. Но UTF8/16/32 и т.д != Unicode. UTF - представление кодировки, где тот же английский текст записывается как один байт на символ, в то время как в Unicode отводится 2 байта на любой символ. В какой бы ты кодировке не грузил файл через QTextStream содержимое будет всегда конвертироваться как cp1251->Unicode, так как ты сам выбрал кодировку для локали. И не важно в какой кодировке сам файл, QTextStream не умеет определять кодировки налету. Поэтому либо вызывай QTextStream::setCodec(), которому подставляй кодировку в которой у тебя файл, либо в конструктор подставляй QString, предварительно считав содержимое из файла (QFile) и преобразовав кодировку вручную. Название: Re: Чтение XML, запись XML Отправлено: sergek от Февраль 26, 2010, 20:15 Цитировать В строчке с stream.readAll() в text текст попадает уже в юникоде. cp1251->Unicode 4.0 Верно.Цитировать Затем мы берем строку text (которая у нас уже в Unicode 4.0) и добавляем в QByteArray. Выбираем кодек UTF-8 и ...: выполняем преобразование Unicode 4.0 в Unicode 4.0, обманывая кодек, сказав ему, что у нас там UTF-8 А это не так. Вы пропустили пару строк из моего поста:Код: QByteArray xml; Для всех других русских букв, кроме "И" это выполняется, попробуйте. Цитировать QTextStream не умеет определять кодировки налету Если есть BOM, то умеет.В общем, пока причина непонятна. Но то, что мне нужно, я получил - просто выкинул QTextStream за ненадобностью: Цитировать QFile file(fileName); Таким образом, взаимная перекодировка устранена, глюков нет.file.open(QFile::ReadOnly | QFile::Text); QByteArray xml=file.readAll(); Спасибо за подсказки. Название: Re: Чтение XML, запись XML Отправлено: SABROG от Февраль 27, 2010, 00:52 В общем, пока причина непонятна. Возможно происходит что-то о чем сказано здесь: Цитировать Warning: Some codecs do not preserve the characters in the ASCII range (0x00 to 0x7F). For example, the Japanese Shift-JIS encoding maps the backslash character (0x5A) to the Yen character. To avoid undesirable side-effects, we recommend avoiding such codecs with setCodecsForCString(). Для проверки верни QTextStream и просто вызови QByteArray::append(). А потом сохрани его содержимое в файл. Я никогда не использовал глобальную установку кодеков вручную и делать этого никогда не буду и никому не советую. Название: Re: Чтение XML, запись XML Отправлено: sergek от Март 01, 2010, 10:34 Цитировать У меня все кодеки одинаковые, поэтому должно выполняться обратное преобразование Unicode->cp1251, и в xml текст должен быть в честном UTF-8 Причина, более-менее, понятна - в неэквивалентности прямых и обратных преобразований. Наверное, можно выстроить эти цепочки, но я сделал по-другому. XML-файл загружаю в QByteArray, сохраняя кодировку. Затем определяю кодировку этого файла, используя QXmlSimpleReader преобразую исходный текст честным кодеком (соответствующим кодировке) в unicode - для его просмотра и редактирования. Когда нужен исходный текст, выполняю обратное преобразование из unicode в первоначальную кодировку. В общем, решение очевидное.Цитировать Я никогда не использовал глобальную установку кодеков вручную и делать этого никогда не буду и никому не советую Прокомментируйте, пожалуйста. Например, чем плох вариант:Код: QTextCodec * codec = QTextCodec::codecForLocale(); Название: Re: Чтение XML, запись XML Отправлено: SABROG от Март 01, 2010, 13:47 Слово "вручную" означало в данном контексте "жестко заданную". В то время как codecForLocale() автоматическая, это я использую в своих приложениях и то для нормального вывода отладочной информации в консоль.
А вот это явно лишнее. Кодировка исходников может не совпадать с кодировкой локали. Код: QTextCodec::setCodecForTr(codec); Название: Re: Чтение XML, запись XML Отправлено: sergek от Март 01, 2010, 14:10 Еще вопрос. Для определения кодировки исходного xml-файла в обработчике QXmlSimplReader я делаю
Код: class CUfebsHandler : public QXmlDefaultHandler Название: Re: Чтение XML, запись XML Отправлено: SABROG от Март 01, 2010, 14:28 Остается ощущение, что это велосипед. Нет ли стандартных средств? Есть. Все классы использующие QXmlInputSource автоматически определяют кодировку, если они не могут её определить, то используется UTF-8 или UTF-16. Название: Re: Чтение XML, запись XML Отправлено: sergek от Март 02, 2010, 10:24 Цитировать Все классы использующие QXmlInputSource автоматически определяют кодировку Я в этом и не сомневался :) А выдают ли они ее наружу? Как в обработчиках получить значение encoding из декларации?Название: Re: Чтение XML, запись XML Отправлено: SABROG от Март 02, 2010, 12:38 Не выдают. Кодек хранится в указателе d_ptr (QXmlSimpleReaderPrivate) private секции класса QXmlSimpleReader. Достучаться можно унаследовав QXmlSimpleReader через using.
Название: Re: Чтение XML, запись XML Отправлено: sergek от Март 12, 2010, 22:59 Коллеги! Проект (библиотека для работы с xml-документами определенного формата), в связи с которым я и начал этот топик, почти завершен. Если есть желание, можно ознакомиться с ним по ссылке:
http://get.freesoft.ru/?id=106788 (http://get.freesoft.ru/?id=106788) Архив включает скомпилированный демонстрационный пример для Windows. Если влом тянуть весь проект (4.6 Мб), можно ознакомиться с документацией на него (руководство программиста): http://get.freesoft.ru/?id=106789 (http://get.freesoft.ru/?id=106789) Надеюсь, что вы найдете там кое-что полезное, тем более, что я попытался выработать некоторый общий подход к решению подобных задач. Если кто-то не сочтет за труд это прочитать и высказать свои суждения, буду весьма признателен. Со своей стороны прошу all поделиться функцией формирования суммы прописью, которую можно было бы включить в библиотеку. Собственно, у меня есть такая, но я не знаю автора, и неудобно включать ее во фриварный софт. Название: Re: Чтение XML, запись XML Отправлено: sergek от Март 21, 2010, 15:36 Выпущена новая версия библиотеки (ссылки выше исправлены). Если кому интересно, обновления смотрите на сайте, указанном в документации (после модерации программы).
Тему завершаю, всем спасибо. Название: Re: [решено] Чтение XML, запись XML Отправлено: voronElf от Март 22, 2010, 09:09 Насчет формирования суммы прописью, отдаю свою как есть. Только писал давно, зеленый был, ногами сильно не бить )))
Код: QString CModDocs::priceToText(double price) |