Функции qtdom


Содержание

LXXXIX. qtdom functions

Это расширение является ЭКСПЕРИМЕНТАЛЬНЫМ . Поведение этого расширения, включая имена его функций и относящуюся к нему документацию может измениться в последующих версиях PHP без уведомления. Используйте это расширение на свой страх и риск.

Замечание: Для Windows-платформ это расширение недоступно.

You need the Qt-library >=2.2.0

Configure PHP —with-qtdom to use these functions.

qtdom Функции

Содержание

  • qdom_error — Returns the error string from the last QDOM operation or FALSE if no errors occurred
  • qdom_tree — Creates a tree of an XML string
Внимание
НОВОСТИ ФОРУМА
Рыцари теории эфира
01.10.2020 — 05:20: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Youtube]69vJGqDENq4[/Youtube][/center]
[center]14:36[/center]
Osievskii Global News
29 сент. Отправлено 05:20, 01.10.2020 г.’ target=_top>Просвещение от Вячеслава Осиевского — Карим_Хайдаров.
30.09.2020 — 12:51: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Ok]376309070[/Ok][/center]
[center]11:03[/center] Отправлено 12:51, 30.09.2020 г.’ target=_top>Просвещение от Дэйвида Дюка — Карим_Хайдаров.
30.09.2020 — 11:53: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Youtube]VVQv1EzDTtY[/Youtube][/center]
[center]10:43[/center]

интервью Раввина Борода https://cursorinfo.co.il/all-news/rav.
мой телеграмм https://t.me/peshekhonovandrei
мой твиттер https://twitter.com/Andrey54708595
мой инстаграм https://www.instagram.com/andreipeshekhonow/

[b]Мой комментарий:
Андрей спрашивает: Краснодарская синагога — это что, военный объект?
— Да, военный, потому что имеет разрешение от Росатома на манипуляции с радиоактивными веществами, а также иными веществами, опасными в отношении массового поражения. Именно это было выявлено группой краснодарцев во главе с Мариной Мелиховой.

[center][Youtube]CLegyQkMkyw[/Youtube][/center]
[center]10:22 [/center]

Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ):
https://tainy.net/22686-predskazaniya-dominika-rikardi-o-budushhem-rossii-sdelannye-v-2000-godu.html

Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором)
http://av-inf.blogspot.com/2013/12/dalles.html

[center][b]Сон разума народа России [/center]

[center][Youtube]CLegyQkMkyw[/Youtube][/center]
[center]10:22 [/center]

Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ):
https://tainy.net/22686-predskazaniya-dominika-rikardi-o-budushhem-rossii-sdelannye-v-2000-godu.html

Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором)
http://av-inf.blogspot.com/2013/12/dalles.html

[center][b]Сон разума народа России [/center]

Способы обработки XML в Qt — Stream, SAX, DOM

Многие сталкивались с XML-документами и знают что это такое, ведь стандарт рассматриваемого языка разметки опубликован в далеком 1998 году. Язык XML используется во многих областях, но чаще всего для передачи информации через Internet — не случайно стандарт разработан Консорциумом Всемирной паутины (W3C) [1].

Очень много информации в этом мире записано и передается в формате XML, например ленты новостей RSS и Atom. В связи с этим не будут лишними навыки использования библиотек для обработки XML-файлов.

В статье рассмотрены три варианта разбора файлов в формате XML средствами библиотеки Qt. В качестве примера используется файл, возвращаемый Центральным банком Российской Федерации на запрос курса доллара в заданный период [2].

Для получения файла с курсом валюты на сайт Центрального банка высылается запрос. Используется QNetworkAccessManager, подробно описанный в статье «Получение данных с сайта. Шаблон Producer/Consumer» [3]. Данные, извлеченные из файла, выводятся на график средствами библиотеки Qwt [4].

рис. 1 Снимок окна с графиком курсов валют

Содержание:

Архитектура приложения, запрос курса валют

Класс RateReceiver передает запрос курса доллара сайту Центрального банка и осуществляет обработку, приходящего в ответ XML-файла. Когда ответ от сайта будет полностью получен, объект класса QNetworkAccessManager вырабатывает сигнал finished(), связанный со слотом on_load класса RateReceiver. В слоте on_load() из входного файла выделяется информация для построения графика и передается с сигналами rate() экземпляру MainWidget. По завершению обработки файла вырабатывается сигнал loadFinished().

Объект класса MainWidget накапливает данные о курсах валют в векторе, а затем, по приходу сигнала loadFinished(), выводит точки на график.

рис. 2 UML диаграмма классов

На диаграмме классов показано, что RateReceiver сам справляется с обработкой входного файла в слоте on_load и, лишь при использовании SAX-интерфейса (см. ниже), работа с файлом делегируется отдельному объекту (XmlSaxHandler).

Код приведен схематично, внимание можно обратить на слот rateRequest, производящий запрос к сайту Центрального банка. В запросе передаются параметры — начало и конец временного интервала, код валюты. Для передачи параметров запроса в библиотеке Qt используется класс QUrlQuery.

Средства обработки XML в библиотеке Qt

В библиотеку Qt включены три класса, реализующих различные подходы к обработке XML-документов:

  • QXmlStreamReader [5], воспринимает документ в виде потока тегов. Интерфейс класса позволяет перемещаться по этому набору. Класс предоставляет самый быстрый обработки XML-документов, однако об иерархической структуре документа класс ничего не знает и не подходит для добавления информации в документ;
  • QXmlSimpleReader [6], реализует SAX-интерфейс (Java API) для работы с XML. Фактически, является тем же QXmlStreamReader, но в другой обертке — при считывании тега в объекте-обработчике вызывается виртуальная функция, соответствующая типу тега. Функция-обработчик ничего не знает о предыдущих вызовах и обрабатывает только текущий тег, поэтому требует также мало памяти, как QXmlStreamReader и не подходит для изменения документа;
  • QDomDocument [7], реализует DOM-интерфейс (W3C API) обработки XML. Считывает весь документ в память в виде дерева, поэтому не рекомендуется для обработки больших документов. Позволяет изменять дерево и, соответственно, документ.

Пример использования QXmlStreamReader

Объект класса QXmlStreamReader может быть инициирован открытым файлом или массивом байт, содержащим XML-документ. Вызов метода readNext() приводит к считыванию следующего токена и возвращает его тип (TokenType). Из множества типов токенов нас будут интересовать StartElement и EndElement, отвечающие за открывающий и закрывающий тэги соответственно. Тэг имеет имя, которое возвращает метод name(), и набор атрибутов. Набор атрибутов (QXmlStreamAttributes) можно получить методом attributes(), он представляет собой вектор именованных атрибутов. Для обращения к атрибуту по имени используется метод value().

Во время работы приведенного листинга в памяти одновременно будет находиться информация, связанная лишь с одним тегом. Для файлов сложной структуры код может быть очень запутанным — в этих случаях предпочтительно использовать SAX.

Пример использования QXmlSimpleReader

При использовании SAX полномочия на разбор файла делегируются экземпляру класса QXmlSimpleReader, с сигналами которого в конструктору должны быть связаны слоты.

Теперь класс RateReceiver является лишь посредником в передаче сигнала. При получении файла с сервера RateReceiver вызывает метод setData, чем инициирует обработку файла и выдачу сигналов.

Класс XmlSaxHandler наследует виртуальные методы, которые вызываются при считывании парсером лексемы определенного типа — startElement(), endElement(), characters(), а также метод fatalError(), срабатывающий при возникновении ошибки. Все перечисленные методы возвращают true если обработка прошла успешно, иначе — false.

Каждая лексема обрабатывается независимо от других, поэтому чтобы сохранить информацию (например дату и значение курса валюты) нужно добавлять поля класса. По той же причине парсер не владеет информацией о контексте, в котором использована лексема — если требуется учитывать иерархическую вложенность тегов, можно ввести дополнительное поле, отвечающее за состояние парсера.

Пример использования QDomDocument

При использовании QDomDocument файл целиком помещается в память в виде дерева, за счет этого, мы можем достаточно быстро найти определенный узел и без труда модифицировать дерево.


Для получения корня дерева используется метод documentElement(). Все остальные узлы (QDomNode) дерева являются дочерними для других узлов, получить первый дочерний узел можно методом firstChild(), перейти к следующему узлу — методом nextSibling(). У узла есть имя, возвращаемое методом nodeName() и набор именованных атрибутов (QDomNamedNodeMap). Получить набор, ассоциированных атрибутов можно методом attributes(), получить узел атрибута по имени — методом namedItem(). Атрибут является обычным узлом дерева (QDomNode), поэтому его значение возвращает метод nodeValue().

Последний пример учитывает то, что тег Value должен встречаться лишь внутри тега Record, а тег Record является дочерним для ValCurs. При использовании QXmlStreamReader и QXmlSimpleReader мы не обращали на это внимание. Если требуется учитывать иерархическую вложенность тегов, то удобнее использовать либо модель DOM, либо вводить состояния в модели SAX.

Если необходимо часто изменять документ, то альтернативы DOM нет, т.к. SAX и Stream рассматривают документ как обычный текстовый файл, добавить данные в середину которого невозможно. Если же изменения вносятся достаточно редко, то возможно создавать новый документ на основе старого, используя обычный файловый поток (QTextStream), при этом во время записи требуется экранировать служебные символы методом Qt::escape().

Ось времени Qwt

На рисунке 1 можно заметить необычную горизонтальную ось на графике. Установка осей в Qwt выполняется методом setAxisScaleDraw(), аргументом которого должен являться объект, которому будет делегироваться обязанность отрисовки значений на оси. Чтобы создать свою собственную ось, достаточно породить наследника класса QwtScaleDraw и реализовать в нем виртуальный метод label(double v).

Исходный код примеров проекта можно скачать. Для сборки требуется установить библиотеку Qwt и в файле проекта изменить путь к ней.

Описание класса QDomDocument
[модуль QtXml]

Класс QDomDocument служит для представления XML документа. Далее.

Примечание: Все функции в классе реентерабельны.

Открытые функции

Подробное описание

Класс QDomDocument служит для представления XML документа.

Класс QDomDocument представляет весь XML документ. В принципе, это корень документа и отправная точка для анализа содержащихся в документе данных.

Поскольку элементы, текстовые узлы, комментарии, инструкции обработки и т.д., не могут существовать вне контекста документа, в этом классе также содержатся функции-фабрики, необходимые для создания таких объектов. Объекты узлов создаются с помощью фукнции ownerDocument(), которая связывает их с документом, учитывая контекст, в котором они были созданы. Наиболее часто используемыми DOM классами являются QDomNode, QDomDocument, QDomElement и QDomText.

При разботе XML документ представляется в виде дерева объектов, в качестве которых можно использовать классы QDom. Все объекты классов QDom являются всего лишь ссылками на внутреннее дерево. Объекты внутреннего дерева существуют до тех пор, пока на них есть ссылки объектов классов QDom и пока существует объект QDomDocument.

При создании элементов, текстовых узлов и т.д. используются различные функции-фабрики, реализованные в этом классе. Использование конструкторов по-умолчанию классов QDom приведет к созданию пустых объектов, которыми невозможно будет манипулировать или вставлять в документ.

Класс QDomDocument имеет несколько функций для создания данных, например, createElement(), createTextNode(), createComment(), createCDATASection(), createProcessingInstruction(), createAttribute() и createEntityReference(). Некоторые из этих фукнций имеют реализации, поддерживающие пространства имен: createElementNS() и createAttributeNS(). Функция createDocumentFragment() используется для манипулирования частью документа; это может быть полезно при работе со сложными документами.

Содержимое документа устанавливается с помощью setContent(). Эта фукнция анализирует строку как XML документ и создает по нему DOM дерево. Корневой элемент доступен через фукнцию documentElement(). Текстовое представление документо может быть получено с помощью фукнции toString().

Можно вставить узлы из одного документа в другой с помощью фукнции importNode().

Вы можете получить список всех элементов, которые имеют одно имя, посредстовм elementsByTagName() или elementsByTagNameNS().

Пример использования классов QDom приведен ниже:

После того, как doc и elem выйдут из области видимости, все внутреннее дерево, представляющее XML документ, будет уничтожено.

Пример создания документа, используя DOM, приведен ниже:

Для получения более подробной информации о Document Object Model смотрите спецификацию DOM Уровень 1 и Уровень 2 .

Описание функций-членов

QDomDocument::QDomDocument ()

Создает пустой документ.

QDomDocument::QDomDocument ( const QString & name )

Создает документ и устанавливает название типа документа как name.

QDomDocument::QDomDocument ( const QDomDocumentType & doctype )

Создает документ с типом doctype.

QDomDocument::QDomDocument ( const QDomDocument & x )

Создает кописю x.

Данные в копиях общие (поверхностное копирование): изменение одной повлечет за собой изменение и другой. Если вы хотите использовать глубокое копирование, воспользуйтесь функцией cloneNode().

QDomDocument::

Уничтожает объекты и освобождает их ресурсы.

QDomAttr QDomDocument::createAttribute ( const QString & name )

Создает новый атрибут, который называется name и может быть вставлен в элемент (используя QDomElement::setAttributeNode()).

Если name не является правильным XML именем, поведение функции определеяется QDomImplementation::InvalidDataPolicy.

QDomAttr QDomDocument::createAttributeNS ( const QString & nsURI, const QString & qName )

Создает новый атрибут с поддержкой пространств имен, который может быть вставлен в элемент. Имя атрибута — qName, а ссылка пространства имен — nsURI. Эта фукнция также устанавливает QDomNode::prefix() и QDomNode::localName() в соответствующие значения (зависящие от qName).

Если qName не является правильным XML именем, поведение функции определеяется QDomImplementation::InvalidDataPolicy.

QDomCDATASection QDomDocument::createCDATASection ( const QString & value )

Создает новую облать CDATA и помещает value в качестве ее содержимого. Может быть вставлено в документ с помощью QDomNode::appendChild().

Если value содержит символы, которые не могут быть сохранены в CDATA, поведение фукнции определяется QDomImplementation::InvalidDataPolicy.

QDomComment QDomDocument::createComment ( const QString & value )

Создает новый комментарий из строки value, который может быть вставлен в документ с помощью QDomNode::appendChild().

Если value содержит символы, которые не могут быть сохранены в XML комментарии, поведение фукнции определяется QDomImplementation::InvalidDataPolicy.

QDomDocumentFragment QDomDocument::createDocumentFragment ()


Создает новый фрагмент документа, который может быть использован для хранения части документа, когда производятся комплексные операции над деревом.

QDomElement QDomDocument::createElement ( const QString & tagName )

Создает новый элемент с именем tagName, который может быть вставлен в DOM дерево, используя QDomNode::appendChild().

Если tagName не является корректным XML именем, поведение этой фукнции определяется QDomImplementation::InvalidDataPolicy.

QDomElement QDomDocument::createElementNS ( const QString & nsURI, const QString & qName )

Создает новый элемент с поддержкой пространств имен, который может быть вставлен в DOM дерево. Имя элемента определяется параметром qName, а URI пространства имен — nsURI. Функция также устанавливает QDomNode::prefix() и QDomNode::localName() в соответствующие значения (в зависимости от qName).

Если qName является пустой строкой, возвращается нулевой элемент.

QDomEntityReference QDomDocument::createEntityReference ( const QString & name )

Создает новую сущность с именем name, которая может быть вставлена в документ с помощью функции QDomNode::appendChild().

Если name не является корректным XML именем, поведение фукнции определяется QDomImplementation::InvalidDataPolicy.

QDomProcessingInstruction QDomDocument::createProcessingInstruction ( const QString & target, const QString & data )

Создает новую инструкцию обработки, которая может быть добавлена в документ с помощью функции QDomNode::appendChild(). Эта фукнция определяет целью инструкции target и данными data.

Если target не является корректным XML именем, или данные содержат символы, которые не могут быть использованы в инструкции обработки, поведение функции определяется QDomImplementation::InvalidDataPolicy.

QDomText QDomDocument::createTextNode ( const QString & value )

Создает текстовый узел из строки value, который может быть вставлен в дерево документа с помощью функции QDomNode::appendChild().

Если value содержит символы, которые не могут быть сохранены как данные в XML документе (даже в форме символьных ссылок), поведение этих функций определяется QDomImplementation::InvalidDataPolicy.

QDomDocumentType QDomDocument::doctype () const

Возвращает тип текущего документа.

QDomElement QDomDocument::documentElement () const

Возвращает корневой элемент текущего документа.

QDomElement QDomDocument::elementById ( const QString & elementId )

Возвращает элемент, идентификатор (ID) которого равен elementId. Если такой элементы не найден, фукнция возвращает нулевой элемент.

Пока QDomClasses не знает какой из атрибутов является идентификатором, фукнция всегда возвращает null element. Данное поведение может быть изменено в будущих версиях.

QDomNodeList QDomDocument::elementsByTagName ( const QString & tagname ) const

Возвращает QDomNodeList, который содержит все элементы документа с именем tagname. Порядок элементов в списке определяется тем, как они встречаются при обходе в ширину всего дерева.

QDomNodeList QDomDocument::elementsByTagNameNS ( const QString & nsURI, const QString & localName )

Возвращает QDomNodeList, который содержит все элементы документа с локальнцм именем localName и URI пространства имен nsURI. Порядок элементов в списке определяется тем, как они встречаются при обходе в ширину всего дерева.

QDomImplementation QDomDocument::implementation () const

QDomNode QDomDocument::importNode ( const QDomNode & importedNode, bool deep )

Импортирует узел importedNode из другого документа в текущий. importedNode остается в исходном документе; функция создает копию этого элемента, которая может быть использована независимо от исходного документа.

Фукнция возвращает импортированный узел, содержащийся в текущем документе. Возвращенный узел не имеет родителей. Его невозможно импортировать в QDomDocument и в узлы QDomDocumentType. В этом случае фукнция возвращает нулевой узел.

Если deep установлен в true, фукнция импортирует не только узел importedNode, но и целое поддерево; если установлен в false, импортируется только importedNode. Аргумент deep не влияет на QDomAttr и QDomEntityReference узлы, поскольку потомки узлов QDomAttr всегда импортируются, в то время как узлы QDomEntityReference не импортируются никогда.

Поведение этой функции несколько отличается в зависимости от вида узла:

Тип узла Поведение
QDomAttr Элемент-предок устанавливается в 0 и указанный флаг устанавливается в true в порождаемом атрибуте. Целые поддеревья importedNode всегда импортируются с узлами атрибутов: deep ни на что не влияет.
QDomDocument Данные узлы не могут быть импортированы.
QDomDocumentFragment Если deep установлен в true, фукнция импортирует целый фрагмент документа; если нет, то создается пустой фрагмент документа.
QDomDocumentType Данные узлы не могут быть импортированы.
QDomElement Атрибуты, у которых QDomAttr::specified() равно true, также импортируются, в отличие от остальных. Если deep равно true, фукнция также импортирует поддеревья importedNode; в остальных случаях импортируется только элемент (и некоторые атрибуты, смотрите выше).
QDomEntity Узлы сущностей могут быть импортированы, ыно на данный момент нет возможности их использования, поскольку в DOM level 2 документ доступен только для чтения.
QDomEntityReference Потомки узлов сущностей не могут быть импортированы: deep ни на что не влияет.
QDomNotation Узлы нотации XML могут быть импортированы, но на данный момент нет возможности их использования, поскольку в DOM level 2 документ доступен только для чтения.
QDomProcessingInstruction Цель и значение инструкции обработки копируются в новый узел.
QDomText Текст копируется в новый узел.
QDomCDATASection Текст копируется в новый узел.
QDomComment Текст копируется в новый узел.

QDomNode::NodeType QDomDocument::nodeType () const

bool QDomDocument::setContent ( const QByteArray & data, bool namespaceProcessing, QString * errorMsg = 0, int * errorLine = 0, int * errorColumn = 0 )

This function parses the XML document from the byte array data and sets it as the content of the document. It tries to detect the encoding of the document as required by the XML specification.

If namespaceProcessing is true, the parser recognizes namespaces in the XML file and sets the prefix name, local name and namespace URI to appropriate values. If namespaceProcessing is false, the parser does no namespace processing when it reads the XML file.

If a parse error occurs, this function returns false and the error message is placed in *errorMsg, the line number in *errorLine and the column number in *errorColumn (unless the associated pointer is set to 0); otherwise this function returns true. The various error messages are described in the QXmlParseException class documentation. Note that, if you want to display these error messages to your application’s users, they will be displayed in English unless they are explicitly translated.

If namespaceProcessing is true, the function QDomNode::prefix() returns a string for all elements and attributes. It returns an empty string if the element or attribute has no prefix.

Text nodes consisting only of whitespace are stripped and won’t appear in the QDomDocument. If this behavior is not desired, one can use the setContent() overload that allows a QXmlReader to be supplied.

If namespaceProcessing is false, the functions QDomNode::prefix(), QDomNode::localName() and QDomNode::namespaceURI() return an empty string.

Entity references are handled as follows:

  • References to internal general entities and character entities occurring in the content are included. The result is a QDomText node with the references replaced by their corresponding entity values.
  • References to parameter entities occurring in the internal subset are included. The result is a QDomDocumentType node which contains entity and notation declarations with the references replaced by their corresponding entity values.
  • Any general parsed entity reference which is not defined in the internal subset and which occurs in the content is represented as a QDomEntityReference node.
  • Any parsed entity reference which is not defined in the internal subset and which occurs outside of the content is replaced with an empty string.
  • Any unparsed entity reference is replaced with an empty string.

bool QDomDocument::setContent ( const QString & text, bool namespaceProcessing, QString * errorMsg = 0, int * errorLine = 0, int * errorColumn = 0 )

This is an overloaded member function, provided for convenience.

This function reads the XML document from the string text, returning true if the content was successfully parsed; otherwise returns false. Since text is already a Unicode string, no encoding detection is done.

bool QDomDocument::setContent ( QIODevice * dev, bool namespaceProcessing, QString * errorMsg = 0, int * errorLine = 0, int * errorColumn = 0 )


This is an overloaded member function, provided for convenience.

This function reads the XML document from the IO device dev, returning true if the content was successfully parsed; otherwise returns false.

bool QDomDocument::setContent ( const QString & text, QString * errorMsg = 0, int * errorLine = 0, int * errorColumn = 0 )

This is an overloaded member function, provided for convenience.

This function reads the XML document from the string text, returning true if the content was successfully parsed; otherwise returns false. Since text is already a Unicode string, no encoding detection is performed.

No namespace processing is performed either.

bool QDomDocument::setContent ( const QByteArray & buffer, QString * errorMsg = 0, int * errorLine = 0, int * errorColumn = 0 )

This is an overloaded member function, provided for convenience.

This function reads the XML document from the byte array buffer, returning true if the content was successfully parsed; otherwise returns false.

No namespace processing is performed.

bool QDomDocument::setContent ( QIODevice * dev, QString * errorMsg = 0, int * errorLine = 0, int * errorColumn = 0 )

This is an overloaded member function, provided for convenience.

This function reads the XML document from the IO device dev, returning true if the content was successfully parsed; otherwise returns false.

No namespace processing is performed.

bool QDomDocument::setContent ( QXmlInputSource * source, QXmlReader * reader, QString * errorMsg = 0, int * errorLine = 0, int * errorColumn = 0 )

This is an overloaded member function, provided for convenience.

This function reads the XML document from the QXmlInputSource source and parses it with the QXmlReader reader, returning true if the content was successfully parsed; otherwise returns false.

This function doesn’t change the features of the reader. If you want to use certain features for parsing you can use this function to set up the reader appropriately.

QByteArray QDomDocument::toByteArray ( int indent = 1 ) const

Переводит анализируемый документ обратно в его текстовое представление и возвращает QByteArray, содержащий данные в кодировке UTF-8.

Эта фукнция использует indent для определения объема пространства отступа для подэлементов.

QString QDomDocument::toString ( int indent = 1 ) const

Переводет анализируемый документ обратно в его текстовое представление.

Эта фукнция использует indent для определения объема пространства отступа для подэлементов.

QDomDocument & QDomDocument::operator= ( const QDomDocument & x )

Прикрепляет x к текущему DOM документу.

Данные в копиях общие (поверхностное копирование): изменение одного документа повлечет за собой изменение и другого. Если вы хотите использовать глубокое копирование, воспользуйтесь функцией cloneNode().

Если у вас есть перевод, то его можно выложить в Перевод Qt документации на русский язык.

QT 4: программирование GUI на С++ (106 стр.)

Если элементом является

, мы просматриваем список дочерних элементов для поиска узла Text. После его обнаружения мы вызываем функцию toText() для преобразования его в объект типа QDomText и функцию data() для получения текста в виде строки типа QString. Затем мы добавляем текст в разделяемый запятыми список номеров страниц в столбце 1 элемента QTreeWidgetItem.

Давайте теперь посмотрим, как мы можем использовать класс DomParser для синтаксического анализа файла:

01 void parseFile(const QString &fileName)

03 QStringList labels;

07 treeWidget->setWindowTitle(QObject::tr(«DOM Parser»));

09 QFile file(fileName);

Мы начинаем с настройки QTreeWidget. Затем мы создаем объекты QFile и DomParser. При выполнении конструктора DomParser осуществляется синтаксический анализ файла и пополняется виджет дерева.

Как и в предыдущем примере, для сборки приложения с библиотекой QtXml в файл .pro необходимо добавить следующую строку:

Как показывает наш пример, проход по дереву DOM может быть достаточно непростым делом. Простая операция по извлечению текста между тегами

требует обработки в цикле элементов списка при помощи функций firstChild() и nextSibling() класса QDomNode. Программисты, которым очень часто приходится использовать интерфейс DOM, создают свои собственные высокоуровневые функции-оболочки для упрощения выполнения таких наиболее распространенных операций, как извлечение текста между открывающими и закрывающими тегами.

Запись документов XML

Существует два основных подхода к формированию файлов XML в приложениях Qt:

• мы можем построить дерево DOM и вызвать для него функцию save();

• мы можем сформировать файл XML вручную.

Выбор между этими подходами часто не зависит от типа используемого нами интерфейса для чтения документов XML: SAX или DOM.

Ниже приводится фрагмент программного кода, который иллюстрирует способ создания дерева DOM и его записи при помощи QTextStream:

const int Indent = 4;

QDomElement root = doc.createElement(«doc»);

QDomElement quote = doc.createElement(«quote»);


QDomElement translation = doc.createElement(«translation»);

QDomText latin = doc.createTextNode(«Ars longa vita brevis»);

QDomText english = doc.createTextNode(«Art is long, life is short»);

Второй аргумент функции save() задает размер отступа. При ненулевом его значении читаемость сформированного файла будет лучше. Ниже приводится полученный на выходе файл XML:

. Ars longa vita brevis

. Art is long, life is short

Порядок действий будет другим, если в приложении дерево DOM используется в качестве главной структуры данных. В таких случаях приложения обычно считывают документы XML, применяя интерфейс DOM, затем модифицируют в памяти дерево DOM и, наконец, вызывают функцию save() для обратного преобразования дерева в документ XML.

По умолчанию функция QDomDocument::save() использует для генерации файла кодировку UTF-8. Мы можем применить другую кодировку, если добавить XML-объявление, например такое, как

в начало дерева DOM. Следующий фрагмент программного кода показывает, как это делать:

QDomNode xmlNode = doc.createProcessingInstruction(«xml»,

Формирование файлов XML вручную выполняется не намного сложнее, чем при помощи DOM. Мы можем использовать QTextStream и писать строки, как мы бы делали с любым другим текстовым файлом. Наиболее сложным является вставка специальных символов в текст и значения атрибутов. Функция Qt::escape() заменяет символы ‘ ‘ и ‘&’. Ниже приводится пример ее использования:

В статье «Generating XML» (Формирование документов XML) в журнале «Qt Quarterly», доступной в сети Интернет по адресу http://doc.trolltech.com/qq/qq05-generating-xml.html, рассматривается очень простой класс, позволяющий легко формировать файлы XML. Этот класс решает вопросы, связанные со специальными символами, отступами и кодировкой, позволяя нам полностью сконцентрироваться на документе XML, который мы собираемся формировать. Он предназначен для работы с Qt 3, но его очень легко перенести на Qt 4.

Глава 16. Обеспечение интерактивной помощи

Большинство приложений предоставляют своим пользователям систему помощи, работающую в интерактивном режиме. В некоторых случаях эта помощь носит форму коротких сообщений, например, в виде всплывающих подсказок, комментариев в строке состояния и справок «что это такое?». Все это, естественно, поддерживается в Qt. В других случаях система помощи может быть значительно сложнее и может содержать много страниц текста. Для такого рода систем вы можете воспользоваться классом QTextBrowser в качестве простого браузера системы помощи, а также вы можете вызывать из вашего приложения Qt Assistant или другой браузер файлов HTML.

Всплывающие подсказки, комментарии в строке состояния и справки «что это такое?»

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

Мы можем добавлять всплывающие подсказки к любым виджетам путем включения в программный код вызова функции QWidget::setToolTip(). Например:

Для установки всплывающей подсказки для объекта QAction, который может быть добавлен к меню или панели инструментов, мы можем просто вызвать функцию setToolTip() для этой команды. Например:

newAction = new QAction(tr(«&New»), this);

Если мы явно не устанавливаем всплывающую подсказку, QAction автоматически сформирует ее на основе текста команды.

Комментарии в строке состояния (status tip) также представляют собой короткие текстовые сообщения, причем они обычно немного длиннее всплывающих подсказок. При нахождении курсора мышки на кнопке панели инструментов или на строке меню такой комментарий появляется в строке состояния. Для добавления к команде или к виджету отображаемого в строке состояния комментария необходимо вызвать функцию setStatusTip():

newAction->setStatusTip(tr(«Create a new document»));

Qt/C++ — Урок 026. Применение CallBack функции

Для передачи данных в Qt используется система сигналов и слотов, но это не означает, что нельзя применить старый проверенный способ, а именно использование CallBack функций. Дело в том, что использование CallBack функции является несколько более быстродействующим вариантом, чем сигналы и слоты. А также может быть более легким в применении, что касается того, что сигналы желательно отсоединять от слотов, когда объект посылающий сигнал уничтожается в программе и больше не используется. Этот момент особенно актуален, если учитывать то, что в C++ отсутствует сборщик мусора, как в Java или C# .

Принцип работы CallBack функции

Для использования CallBack функций в классе, который должен будет возвращать результат, необходимо объявить указатель на функцию с такой же сигнатурой, как и у функции, которая будет использована в качестве CallBack функции. А для установки указателя на функцию необходимо использовать метод класса для установки этого указателя. То есть в этот метод передаётся указатель на функцию, который устанавливается в CallBack указатель класса, который будет возвращать результат своей деятельности. При этом в данном классе этот указатель используется как обычная функция, которая будет совершать заданные действия в классе, из которого эта функция была установлена в качестве CallBack функции в текущем классе.

Для примера будет использован класс, который отрисовывает квадрат на графической сцене и управляется клавишами W, A, S, D. При движении квадрат должен отсылать данные о своих координатах в класс, в котором был создан. То есть должен вызывать функцию данного класса в качестве своей CallBack функции.

Структура проекта

Для ознакомления с работой CallBack функции используем проект со следующей структурой:

  • mainwindow.h — Заголовочный файл главного окна приложения;
  • mainwindow.cpp — Файл исходных кодов главного окна приложения;
  • square.h — Заголовочный файл класса, объект которого будет использовать CallBack функцию.
  • square.cpp — файл исходных кодов данного класса;

mainwindow.ui

В главном окне в дизайнере закидываем графическую сцену, а объекты класса QLineEdit, в которых будут отображаться координаты создаём и устанавливаем вручную в данное окно. Поскольку данные объекты должны быть объявлены как static. Это же условие должно применяться и для CallBack функции. Она также должна быть объявлена как static .

mainwindow.h

Также в заголовочном файле главного окна объявляем объект класса Square.

mainwindow.cpp

Помимо объявления статических объектов QLineEdit их ещё необходимо и реализовать как функции в файле исходных кодов, иначе компилятор будет объявлять ошибку. Дело в том, что статические объекты обязательно необходимо инициализировать.

square.h

Данный класс наследуется от QGraphicsItem и в нём объявляется указатель для CallBack функции, а также функция для её установки. Функцию для возвращаемых значений необходимо указывать в обязательном порядке.

square.cpp

Данный пример сходен по механике с игрой, поэтому не удивляемся наличию игрового таймера. По слоту, подключённому к сигналу от таймера мы будем реализовывать движения квадрата по графической сцене и передавать его координаты в CallBack функцию. А для проверки состояния целевых кнопок воспользуемся функционалом WinAPI.

В результате у Вас должно получиться Приложение, в котором производится управление зеленым квадратиком, а через CallBack функцию высылаются данные о его координатах в класс главного окна.

В видеоуроке также даны пояснения и продемонстрирована работа Приложения.

Julia: функции и структуры-как-функции

Несмотря на то, что в языке Julia по замыслу отсутствует «классическое» объектно-ориентированное программирование с классами и методами, язык предоставляет средства абстрагирования, ключевую роль в которых играет система типов и элементы функционального программирования. Рассмотрим подробнее второй пункт.

Концепция функций в Julia, вероятно, наиболее похожа на языки из семейства Lisp (если быть точнее, то ветки Lisp-1), и функции можно рассматривать на трёх уровнях: как подпрограммы, как абстракции к некоторой последовательности действий и как данные, представляющие эту абстракцию.

Уровень 1. Функции как подпрограммы

Выделение подпрограмм и присваивание им собственных имён идёт ещё с доисторических времён, когда Фортран считался языком высокого уровня, а Си ещё не было.

В этом понимании средства Julia стандартны. «Особенностью» можно назвать то, что синтаксически нет деления на процедуры и функции. Вне зависимости от того, вызывается подпрограмма для получения некоторого значения или только для выполнения каких-то действий над данными — она называется функцией.

Определение функции начинается с ключевого слова function , за которым в скобках следует список аргументов, последовательность команд, и заканчивает определение слово end :


Отличительностью синтаксиса является унаследованное от Лиспа поведение: для «нормального» возврата значения из функции слово return не обязательно: возвращается значение последнего вычисленного перед end выражения. В примере выше будет возвращено значение переменной sum . Таким образом, return может использоваться в качестве маркера особого поведения функции:

Для функций с коротким определением есть укороченный синтаксис, похожий на математическую запись. Так, вычисление длины гипотенузы по длине катетов можно определить так:

«Безопасное» деление с помощью тернарного оператора можно записать так:

Как можно заметить, для аргументов функции не обязательно указывать типы. С учётом того, как работает JIT-компилятор Julia, «утиная типизация» даже не всегда будет приводить к падению производительности.

Как я постарался продемонстрировать в предыдущей статье, компилятор Julia может выводить тип возвращаемого результата по типам входных аргументов. Поэтому, например, функция safe_division для быстрой работы требует минимальной модификации:

Теперь, если типы обоих аргументов известны на этапе компиляции, тип возвращаемого результата также однозначно выводится, т.к. функция zero(x) возвращает нулевое значение того же типа, что её аргумент (а деление на ноль, согласно IEEE 754, имеет вполне представимое значение в формате чисел с плавающей точкой).

Функции могут иметь фиксированное число позиционных аргументов, позиционные аргументы со значениями по умолчанию, именованные аргументы и переменное число аргументов. Синтаксис:

Уровень 2. Функции как данные

Имя функции может использоваться не только в непосредственных вызовах, но и как идентификатор, с которым связана процедура получения значения. Например:

«Классические» функции, которые принимают функциональный аргумент, — это map , reduce и filter .

map(f, x. ) применяет функцию f к значениям всех элементов из x (или кортежам из i-х элементов) и возвращает результаты как новую коллекцию:

reduce(f, x; init_val) «сводит» коллекцию к одному значению, «разворачивая» цепочку f(f(. f(f(init_val, x[1]), x[2]). ), x[end]) :

Поскольку на самом деле не определено, в каком порядке будет проход массива при редукции, а также то, будет вызываться fn(accum, x) или fn(x, accum) , редукция будет давать предсказуемый результат только с коммутативными или ассоциативными операторами, типа сложения или умножения.

filter(predicate, x) возвращает массив из элементов x , которые удовлетворяют предикату predicate :

Применение функций высшего порядка для операций над массивами вместо написания цикла имеет несколько преимуществ:

  1. код становится короче
  2. map() или reduce() показывают семантику выполняемой операции, тогда в семантике происходящего в цикле нужно ещё разбираться
  3. map() даёт компилятору понять, что операции над элементами массива независимы по данным, что позволяет применить дополнительные оптимизации

Уровень 3. Функции как абстракции

Нередко в map() или filter() нужно использовать функцию, которой не было присвоено собственное имя. Julia в этом случае позволяет выразить абстракцию выполнения операций над аргументом, не вводя для этой последовательности собственное имя. Такая абстракция называется анонимной функцией, или лямбда-функцией (т.к. в математической традиции такие функции обозначаются буквой лямбда). Синтаксис этого представления такой:

Как именованные, так и анонимные функции можно присваивать переменным и возвращать в качестве значений:

Область видимости переменных и лексические замыкания

В норме функции стараются писать таким образом, чтобы все необходимые для вычисления данные были получены через формальные аргументы, т.е. любые имена переменных, которые встречаются в теле — это либо имена формальных аргументов, либо имена переменных, вводимых внутри тела функции.

Про функцию normal() можно сказать, что в её теле все имена переменных связанные, т.е. если мы везде (включая список аргументов) заменим «x» на «m» (или любой другой идентификатор), «y» на «n», а «z» на «sum_of_m_and_n» — смысл выражения не поменяется. В функции strange() имя z является несвязанным, т.е. а) смысл может поменяться, если это имя будет заменено на другое и б) корректность функции зависит от того, была ли на момент вызова функции определена переменная с именем «z».

Вообще говоря, с функцией normal() тоже не всё так чисто:

  1. Что будет, если вне функции определена переменная с именем z?
  2. Символы + и *, вообще-то, тоже являются несвязанными идентификаторами.

С пунктом 2 ничего нельзя поделать, кроме как согласиться — логично, что определения всех используемых функций в системе должны существовать, и будем надеяться, что их реальный смысл соответствует нашим ожиданиям.

Пункт 1 менее очевиден, чем кажется. Дело в том, что ответ зависит от того, где определена функция. Если она определена глобально, то z внутри normal() будет локальной переменной, т.е. даже при наличии глобальной переменной z её значение не перезапишется. Если же определение функции находится внутри блока кода, то при наличии в этом блоке более раннего определения z будет изменено именно значение внешней переменной.

Если тело функции содержит имя внешней переменной, то это имя связывается с тем значением, которое существовало в окружении, где создана функция. Если сама функция экспортируется из этого окружения (например, если она возвращается из другой функции в качестве значения), то она «захватывает» переменную из внутреннего окружения, к которой в новом окружении доступа уже нет. Это называется лексическим замыканием.

Замыкания в основном полезны в двух ситуациях: когда нужно создать функцию по заданным параметрам и когда нужна функция, которая имеет некоторое внутреннее состояние.

Рассмотрим ситуацию с функцией, инкапсулирующей внутреннее состояние:

Case study: всё те же полиномы

В прошлой статье рассмотрено представление полиномов как структур. В частности, одна из структур хранения — это список коэффициентов, начиная с младшего. Для вычисления полинома p в точке x предлагалось вызвать функцию evpoly(p, x) , которая вычисляет полином по схеме Горнера.

Представление полинома в виде структуры не вполне соответствует его интуитивному пониманию как математической функции. Но с помощью возврата функционального значения можно задавать полиномы и напрямую как функции. Итак, было:

Переделаем это определение в функцию, которая принимает массив / кортеж коэффициентов и возвращает собственно функцию, вычисляющую полином:

Аналогично можно написать функцию и для интерполяционного полинома.

Важный вопрос: а было ли в предыдущем определении что-то, что в новом потерялось? К сожалению, да — задание полинома как структуры давало подсказки для компилятора, а для нас — возможность перегрузить для этой структуры арифметические операторы. Для функций такой мощной системы типов Julia, увы, не предоставляет.

К счастью, в этом случае мы можем взять лучшее из двух миров, поскольку Julia позволяет создавать так называемые callable structs. Т.е. можно задать полином как структуру, но иметь возможность его вызова как функции! К определениям структур из предыдущей статьи нужно лишь добавить:

С помощью функциональных аргументов можно также добавить внешний конструктор интерполяционного полинома для некоторой функции, построенный по набору точек:

Чтение документов XML при помощи интерфейса DOM

Чтение документов XML при помощи интерфейса DOM

DOM является стандартным программным интерфейсом синтаксического анализа документов XML, который разработан Консорциумом всемирной паутины (W3C). Qt обеспечивает уровень 2 интерфейса DOM для чтения, обработки и записи документов XML без проверки их достоверности.

DOM представляет файл XML в памяти в виде дерева. Мы можем просматривать дерево DOM столько раз, сколько нам нужно, и мы можем модифицировать и записывать его на диск в виде файла XML.

Давайте рассмотрим следующий документ XML:

Ars longa vita brevis

Art is long, life is short

Ему соответствует следующее дерево DOM:

Дерево DOM содержит узлы разных типов. Например, узел Element соответствует открывающему тегу и связанному с ним закрывающему тегу. Все, что располагается между этими тегами, представляется в виде дочерних узлов данного элемента Element.

В Qt различные типы таких узлов (как и все другие связанные с DOM классы) имеют префикс QDom. Так, QDomElement представляет узел Element, a QDomText представляет узел Text.

Различные узлы могут иметь дочерние узлы разных типов. Например, узел Element может содержать другие узлы Element, а также узлы EntityReference, Text, CDATASection, ProcessingInstruction и Comment. Рис. 15.3 показывает, какие типы дочерних узлов допустимы для соответствующих родительских узлов. Узлы, показанные серым, не могут иметь дочерних узлов.


Рис. 15.3. Родственные связи между узлами DOM.

Для иллюстрации применения DOM при чтении файлов XML мы напишем парсер для файла предметного указателя книги, описанного в предыдущем разделе.

01 class DomParser

04 DomParser(QIODevice *device, QTreeWidget *tree);

06 void parseEntry(const QDomElement &element,

07 QTreeWidgetItem *parent);

08 QTreeWidget *treeWidget;

Мы определяем класс с названием DomParser, который выполняет синтаксический анализ предметного указателя книги, представленного в виде документа XML, и отображает результат в виджете QTreeWidget. Этот класс не наследует никакой другой класс.

01 DomParser::DomParser(QIODevice *device, QTreeWidget *tree)

04 QString errorStr;

05 int errorLine;

06 int errorColumn;

07 QDomDocument doc;

08 if (!doc.setContent(device, true, &errorStr,

09 &errorLine, &errorColumn)) <

10 QMessageBox::warning(0, QObject::tr(«DOM Parser»),

11 QObject::tr(«Parse error at line %1, column %2: %3»)

15 QDomElement root = doc.documentElement();

16 if (root.tagName() != «bookindex»)

18 QDomNode node = root.firstChild();

19 while (!node.isNull()) <

20 if (node.toElement().tagName() == «entry»)

21 parseEntry(node.toElement(), 0);

22 node = node.nextSibling();

В конструкторе мы создаем объект QDomDocument и вызываем для него функцию setContent(), чтобы с его помощью прочесть документ XML с устройства QIODevice. Функция setContent() автоматически открывает устройство, если оно еще не открыто. Затем мы вызываем функцию documentElement() для объекта QDomDocument, чтобы получить его одиночный дочерний элемент QDomElement, после чего мы проверяем, является ли данный элемент . Мы выполняем цикл по всем дочерним узлам, и если узлом является элемент , мы вызываем функцию parseEntry() для его синтаксического анализа.

Класс QDomNode может хранить узлы любого типа. Если мы хотим продолжить обработку узла, мы должны сначала преобразовать его в правильный тип данных. В нашем примере нас интересуют только узлы Element, и поэтому мы вызываем функцию toElement() объекта QDomNode для преобразования его в объект QDomElement и затем вызова функции tagName() для получения имени тега элемента. Если данный узел не имеет тип Element, функция toElement() возвращает нулевой объект типа QDomElement, содержащий пустое имя тега.

01 void DomParser::parseEntry(const QDomElement &element,

02 QTreeWidgetItem *parent)

04 QTreeWidgetItem *item;

06 item = new QTreeWidgetTtem(parent);

08 item = new QTreeWidgetItem(treeWidget);

10 item->setText(0, element.attribute(«term»));

11 QDomNode node = element.firstChild();

12 while (!node.isNull()) <

13 if (node.toElement().tagName() == «entry») <

14 parseEntry(node.toElement(), item);

15 > else if (node.toElement().tagName() == «page») <

16 QDomNode childNode = node.firstChild();

17 while (!childNode.isNull()) <

18 if (childNode.nodeType() == QDomNode::TextNode) <

19 QString page = childNode.toText().data();

20 QString allPages = item->text(1);

21 if (!allPages.isEmpty())

23 allPages += page;

24 item->setText(1, allPages);

27 childNode = childNode.nextSibling();

30 node = node.nextSibling();

В функции parseEntry() мы создаем элемент объекта QTreeWidget. Если тег вложен в другой , новый тег определяет подэлемент предметного указателя, и мы создаем элемент QTreeWidgetItem как дочерний для внешнего элемента QTreeWidgetItem. В противном случае мы создаем элемент QTreeWidgetItem с treeWidget в качестве его родительского элемента, делая его элементом верхнего уровня. Мы вызываем функцию setText() для установки текста столбца 0 на значение атрибута term тега .

После инициализации нами элемента QTreeWidgetItem мы выполняем цикл по дочерним узлам элемента QDomElement, который соответствует текущему тегу .


Если элементом является , мы вызываем функцию parseEntry(), передавая текущий элемент в качестве второго аргумента. Затем будет создан новый элемент QTreeWidgetItem, в качестве родительского элемента которого выступает внешний элемент QTreeWidgetItem.

Если элементом является

, мы просматриваем список дочерних элементов для поиска узла Text. После его обнаружения мы вызываем функцию toText() для преобразования его в объект типа QDomText и функцию data() для получения текста в виде строки типа QString. Затем мы добавляем текст в разделяемый запятыми список номеров страниц в столбце 1 элемента QTreeWidgetItem.

Давайте теперь посмотрим, как мы можем использовать класс DomParser для синтаксического анализа файла:

01 void parseFile(const QString &fileName)

03 QStringList labels;

07 treeWidget->setWindowTitle(QObject::tr(«DOM Parser»));

09 QFile file(fileName);

Мы начинаем с настройки QTreeWidget. Затем мы создаем объекты QFile и DomParser. При выполнении конструктора DomParser осуществляется синтаксический анализ файла и пополняется виджет дерева.

Как и в предыдущем примере, для сборки приложения с библиотекой QtXml в файл .pro необходимо добавить следующую строку:

Как показывает наш пример, проход по дереву DOM может быть достаточно непростым делом. Простая операция по извлечению текста между тегами

требует обработки в цикле элементов списка при помощи функций firstChild() и nextSibling() класса QDomNode. Программисты, которым очень часто приходится использовать интерфейс DOM, создают свои собственные высокоуровневые функции—оболочки для упрощения выполнения таких наиболее распространенных операций, как извлечение текста между открывающими и закрывающими тегами.

Способы обработки XML в Qt — Stream, SAX, DOM

Многие сталкивались с XML-документами и знают что это такое, ведь стандарт рассматриваемого языка разметки опубликован в далеком 1998 году. Язык XML используется во многих областях, но чаще всего для передачи информации через Internet — не случайно стандарт разработан Консорциумом Всемирной паутины (W3C) [1].

Очень много информации в этом мире записано и передается в формате XML, например ленты новостей RSS и Atom. В связи с этим не будут лишними навыки использования библиотек для обработки XML-файлов.

В статье рассмотрены три варианта разбора файлов в формате XML средствами библиотеки Qt. В качестве примера используется файл, возвращаемый Центральным банком Российской Федерации на запрос курса доллара в заданный период [2].

Для получения файла с курсом валюты на сайт Центрального банка высылается запрос. Используется QNetworkAccessManager, подробно описанный в статье «Получение данных с сайта. Шаблон Producer/Consumer» [3]. Данные, извлеченные из файла, выводятся на график средствами библиотеки Qwt [4].

рис. 1 Снимок окна с графиком курсов валют

Содержание:

Архитектура приложения, запрос курса валют

Класс RateReceiver передает запрос курса доллара сайту Центрального банка и осуществляет обработку, приходящего в ответ XML-файла. Когда ответ от сайта будет полностью получен, объект класса QNetworkAccessManager вырабатывает сигнал finished(), связанный со слотом on_load класса RateReceiver. В слоте on_load() из входного файла выделяется информация для построения графика и передается с сигналами rate() экземпляру MainWidget. По завершению обработки файла вырабатывается сигнал loadFinished().

Объект класса MainWidget накапливает данные о курсах валют в векторе, а затем, по приходу сигнала loadFinished(), выводит точки на график.

рис. 2 UML диаграмма классов

На диаграмме классов показано, что RateReceiver сам справляется с обработкой входного файла в слоте on_load и, лишь при использовании SAX-интерфейса (см. ниже), работа с файлом делегируется отдельному объекту (XmlSaxHandler).

Код приведен схематично, внимание можно обратить на слот rateRequest, производящий запрос к сайту Центрального банка. В запросе передаются параметры — начало и конец временного интервала, код валюты. Для передачи параметров запроса в библиотеке Qt используется класс QUrlQuery.

Средства обработки XML в библиотеке Qt

В библиотеку Qt включены три класса, реализующих различные подходы к обработке XML-документов:

  • QXmlStreamReader [5], воспринимает документ в виде потока тегов. Интерфейс класса позволяет перемещаться по этому набору. Класс предоставляет самый быстрый обработки XML-документов, однако об иерархической структуре документа класс ничего не знает и не подходит для добавления информации в документ;
  • QXmlSimpleReader [6], реализует SAX-интерфейс (Java API) для работы с XML. Фактически, является тем же QXmlStreamReader, но в другой обертке — при считывании тега в объекте-обработчике вызывается виртуальная функция, соответствующая типу тега. Функция-обработчик ничего не знает о предыдущих вызовах и обрабатывает только текущий тег, поэтому требует также мало памяти, как QXmlStreamReader и не подходит для изменения документа;
  • QDomDocument [7], реализует DOM-интерфейс (W3C API) обработки XML. Считывает весь документ в память в виде дерева, поэтому не рекомендуется для обработки больших документов. Позволяет изменять дерево и, соответственно, документ.

Пример использования QXmlStreamReader

Объект класса QXmlStreamReader может быть инициирован открытым файлом или массивом байт, содержащим XML-документ. Вызов метода readNext() приводит к считыванию следующего токена и возвращает его тип (TokenType). Из множества типов токенов нас будут интересовать StartElement и EndElement, отвечающие за открывающий и закрывающий тэги соответственно. Тэг имеет имя, которое возвращает метод name(), и набор атрибутов. Набор атрибутов (QXmlStreamAttributes) можно получить методом attributes(), он представляет собой вектор именованных атрибутов. Для обращения к атрибуту по имени используется метод value().

Во время работы приведенного листинга в памяти одновременно будет находиться информация, связанная лишь с одним тегом. Для файлов сложной структуры код может быть очень запутанным — в этих случаях предпочтительно использовать SAX.

Пример использования QXmlSimpleReader

При использовании SAX полномочия на разбор файла делегируются экземпляру класса QXmlSimpleReader, с сигналами которого в конструктору должны быть связаны слоты.

Теперь класс RateReceiver является лишь посредником в передаче сигнала. При получении файла с сервера RateReceiver вызывает метод setData, чем инициирует обработку файла и выдачу сигналов.

Класс XmlSaxHandler наследует виртуальные методы, которые вызываются при считывании парсером лексемы определенного типа — startElement(), endElement(), characters(), а также метод fatalError(), срабатывающий при возникновении ошибки. Все перечисленные методы возвращают true если обработка прошла успешно, иначе — false.

Каждая лексема обрабатывается независимо от других, поэтому чтобы сохранить информацию (например дату и значение курса валюты) нужно добавлять поля класса. По той же причине парсер не владеет информацией о контексте, в котором использована лексема — если требуется учитывать иерархическую вложенность тегов, можно ввести дополнительное поле, отвечающее за состояние парсера.

Пример использования QDomDocument

При использовании QDomDocument файл целиком помещается в память в виде дерева, за счет этого, мы можем достаточно быстро найти определенный узел и без труда модифицировать дерево.

Для получения корня дерева используется метод documentElement(). Все остальные узлы (QDomNode) дерева являются дочерними для других узлов, получить первый дочерний узел можно методом firstChild(), перейти к следующему узлу — методом nextSibling(). У узла есть имя, возвращаемое методом nodeName() и набор именованных атрибутов (QDomNamedNodeMap). Получить набор, ассоциированных атрибутов можно методом attributes(), получить узел атрибута по имени — методом namedItem(). Атрибут является обычным узлом дерева (QDomNode), поэтому его значение возвращает метод nodeValue().

Последний пример учитывает то, что тег Value должен встречаться лишь внутри тега Record, а тег Record является дочерним для ValCurs. При использовании QXmlStreamReader и QXmlSimpleReader мы не обращали на это внимание. Если требуется учитывать иерархическую вложенность тегов, то удобнее использовать либо модель DOM, либо вводить состояния в модели SAX.

Если необходимо часто изменять документ, то альтернативы DOM нет, т.к. SAX и Stream рассматривают документ как обычный текстовый файл, добавить данные в середину которого невозможно. Если же изменения вносятся достаточно редко, то возможно создавать новый документ на основе старого, используя обычный файловый поток (QTextStream), при этом во время записи требуется экранировать служебные символы методом Qt::escape().

Ось времени Qwt

На рисунке 1 можно заметить необычную горизонтальную ось на графике. Установка осей в Qwt выполняется методом setAxisScaleDraw(), аргументом которого должен являться объект, которому будет делегироваться обязанность отрисовки значений на оси. Чтобы создать свою собственную ось, достаточно породить наследника класса QwtScaleDraw и реализовать в нем виртуальный метод label(double v).

Исходный код примеров проекта можно скачать. Для сборки требуется установить библиотеку Qwt и в файле проекта изменить путь к ней.

Использование ui в функции

12.04.2020, 19:15

Использование функции moveToThread
Доброго времени суток. Не знал, как точно озаглавить эту тему, поэтому объясню здесь. У меня.

Использование функции setStyleSheet
Использую код для установки рисунка v_back->setStyleSheet(«border-image.

Использование WinAPI функции в приложении Qt
Вышел спор с преподавателем. Он убеждал меня, что в топку C++ Qt, лучше использовать C#. И вот в.

Использование функции в качестве параметра
Добрый день! У меня есть класс, каждый раз при создании которого, мы соединяем его со слотом. Для.

Использование функции один раз в Qt Creator
Доброго времени суток. При создании калькулятора столкнулась с проблемой: как заставить программу.

Илон Маск рекомендует:  DiskSize - Функция Delphi
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL