Интерфейс SAX
SAX — это стандартный интерфейс на основе событий для парсеров XML. Qt-интерфейс следует структуре SAX2 Java-реализации. Его схема именования была адаптирована к соглашениям об именовании Qt. Подробности о SAX2 можно найти по адресу http://www.saxproject.org.
Поддержка SAX2-фильтров и фабрики читателей находится в стадии разработки. Qt-реализация не включает классы совместимости SAX1, присутствующие в Java-интерфейсе.
Введение в SAX2
Интерфейс SAX2 — это механизм обработки событий, предоставляющий пользователю информацию о документе. «Событие» в данном контексте означает нечто, сообщаемое парсером, например, он встретил открывающий тег или закрывающий тег и т. д.
Для лучшего понимания рассмотрим следующий пример:
<<quote>A quotation.</quote>
При чтении (SAX2-парсер обычно называется «читателем») вышеуказанного документа будут сгенерированы три события:
- Возникает открывающий тег (
<quote>). - Найдено текстовое содержимое, «A quotation.».
- Обработан закрывающий тег (
</quote>).
Каждый раз, когда такое событие возникает, парсер его сообщает; вы можете настроить обработчики событий для реакции на эти события.
Хотя это быстрый и простой подход для чтения XML-документов, манипулирование данными затруднено, поскольку данные не хранятся, а просто обрабатываются и последовательно отбрасываются. Интерфейс DOM считывает и сохраняет весь документ в структуре дерева; это требует больше памяти, но упрощает манипулирование структурой документа.
Модуль Qt XML предоставляет абстрактный класс QXmlReader, который определяет интерфейс для потенциальных SAX2-читателей. Qt включает реализацию читателя QXmlSimpleReader, которую легко адаптировать путем наследования.
Читатель сообщает о событиях обработки с помощью специальных классов-обработчиков:
| Класс-обработчик | Описание |
|---|---|
| QXmlContentHandler | Сообщает о событиях, связанных с содержимым документа (например, об открывающем теге или символах). |
| QXmlDTDHandler | Сообщает о событиях, связанных с DTD (например, объявлениях обозначений). |
| QXmlErrorHandler | Сообщает об ошибках или предупреждениях, произошедших во время обработки. |
| QXmlEntityResolver | Сообщает об внешних сущностях во время обработки и позволяет пользователям самим разрешать внешние сущности вместо того, чтобы оставлять это читателю. |
| QXmlDeclHandler | Сообщает о дополнительных событиях, связанных с DTD (например, объявлениях атрибутов). |
| QXmlLexicalHandler | Сообщает о событиях, связанных с лексической структурой документа (начало DTD, комментарии и т. д.). |
Эти классы являются абстрактными классами, описывающими интерфейс. Класс QXmlDefaultHandler предоставляет реализацию по умолчанию «ничего не делать» для всех них. Таким образом, пользователям нужно только переопределить функции QXmlDefaultHandler, которые их интересуют.
Для чтения входных XML-данных используется специальный класс QXmlInputSource.
Помимо уже упомянутых, следующие классы поддержки SAX2 предоставляют дополнительную полезную функциональность:
| Класс | Описание |
|---|---|
| QXmlAttributes | Используется для передачи атрибутов в событии «открытие элемента». |
| QXmlLocator | Используется для получения фактического положения обработки события. |
| QXmlNamespaceSupport | Используется для реализации поддержки пространств имен для читателя. Обратите внимание, что пространства имен не изменяют поведение парсинга. Они просто сообщаются через обработчик. |
Пример SAX Bookmarks демонстрирует, как наследоваться от QXmlDefaultHandler для чтения файла XML-закладок (XBEL) и как вручную генерировать XML.
Особенности SAX2
Поведение XML-читателя зависит от его поддержки определенных необязательных функций. Например, у читателя может быть функция «сообщать об атрибутах, используемых для декларирования пространств имен и префиксов вместе с локальным именем тега». Как и любая другая функция, она имеет уникальное имя, представленное URI: оно называется http://xml.org/sax/features/namespace-prefixes.
Qt-реализация SAX2 может сообщать, обладает ли читатель определённой функциональностью, используя функцию QXmlReader::hasFeature(). Доступные функции можно проверить с помощью QXmlReader::feature(), а включить или выключить их с помощью QXmlReader::setFeature().
Рассмотрим пример
<<document xmlns:book = 'http://example.com/fnord/book/'
xmlns = 'http://example.com/fnord/' > Читатель, который не поддерживает функцию http://xml.org/sax/features/namespace-prefixes, сообщит имя элемента document, но не сообщит его атрибуты xmlns:book и xmlns со своими значениями. Читатель с функцией http://xml.org/sax/features/namespace-prefixes сообщает о атрибутах пространства имён, если функция feature включена.
Другие функции включают http://xml.org/sax/features/namespace (обработка пространств имён, подразумевает http://xml.org/sax/features/namespace-prefixes) и http://xml.org/sax/features/validation (возможность сообщать об ошибках валидации).
Хотя SAX2 оставляет пользователю определение и реализацию необходимых функций, поддержка http://xml.org/sax/features/namespace (и, следовательно, http://xml.org/sax/features/namespace-prefixes) является обязательной. Реализация QXmlSimpleReader класса QXmlReader поддерживает их и может выполнять обработку пространств имён.
QXmlSimpleReader не является валидирующим, поэтому он не поддерживает http://xml.org/sax/features/validation.
Поддержка пространств имен через функции
Как мы видели в предыдущем разделе, мы можем настроить поведение читателя при обработке пространств имен. Это делается путём включения и отключения функций http://xml.org/sax/features/namespaces и http://xml.org/sax/features/namespace-prefixes.
Они влияют на поведение отчётности следующим образом:
- Префиксы пространств имён и локальные части элементов и атрибутов могут быть сообщены.
- Сообщаются квалифицированные имена элементов и атрибутов.
- QXmlContentHandler::startPrefixMapping() и QXmlContentHandler::endPrefixMapping() вызываются читателем.
- Отчитываются атрибуты, которые декларируют пространства имен (т. е. атрибут xmlns и атрибуты, начинающиеся с xmlns:).
Рассмотрим следующий элемент:
<<author xmlns:fnord = 'http://example.com/fnord/'
title="Ms"
fnord:title="Goddess"
name="Eris Kallisti"/> При установке http://xml.org/sax/features/namespace-prefixes в значение true, читатель сообщит о четырёх атрибутах; но при установке функции namespace-prefixes в значение false, он сообщит только о трёх, а атрибут xmlns:fnord, определяющий пространство имён, будет «невидимым» для читателя.
Функция http://xml.org/sax/features/namespaces отвечает за сообщение локальных имён, префиксов пространств имён и URI. При установке http://xml.org/sax/features/namespaces в значение true, парсер сообщит title как локальное имя атрибута fnord:title, fnord — как префикс пространства имён и http://example.com/fnord/ — как URI пространства имён. При значении http://xml.org/sax/features/namespaces в false, ни одно из них не будет сообщено.
В текущей реализации классы Qt XML следуют определению, что префикс xmlns сам по себе не связан ни с каким пространством имён (см. http://www.w3.org/TR/1999/REC-xml-names-19990114/#ns-using). Поэтому даже при установке http://xml.org/sax/features/namespaces и http://xml.org/sax/features/namespace-prefixes в значение true, читатель не вернёт ни локальное имя, ни префикс пространства имён, ни URI пространства имён для xmlns:fnord.
Это может быть изменено в будущем, следуя предложению W3C http://www.w3.org/2000/xmlns/ о связи xmlns со пространством имён http://www.w3.org/2000/xmlns.
Как подсказывает стандарт SAX2, QXmlSimpleReader по умолчанию имеет http://xml.org/sax/features/namespaces в значении true и http://xml.org/sax/features/namespace-prefixes в значении false. При изменении этого поведения с помощью QXmlSimpleReader::setFeature() обратите внимание, что сочетание обоих значений в false является недопустимым.
Резюме
QXmlSimpleReader реализует следующее поведение:
| (namespaces, namespace-prefixes) | Префикс пространства имен и локальная часть | Квалифицированные имена | Сопоставление префиксов | Атрибуты xmlns |
|---|---|---|---|---|
| (true, false) | Да | Да* | Да | Нет |
| (true, true) | Да | Да | Да | Да |
| (false, true) | Нет* | Да | Нет* | Да |
| (false, false) | Недопустимо | |||
Поведение записей, помеченных звёздочкой (*), не определено стандартом SAX.
Свойства
Свойства — это более общее понятие. Они имеют уникальное имя, представленное URI, но их значение — void*. Таким образом, в качестве значения свойства можно использовать практически всё. Однако это понятие сопряжено с некоторыми опасностями: нет никакого способа гарантировать безопасность типов; пользователь должен позаботиться о том, чтобы передавать правильный тип. Свойства полезны, если читатель поддерживает специальные классы-обработчики.
URI, используемые для функций и свойств, часто похожи на URL, например, http://xml.org/sax/features/namespace. Это не означает, что необходимые данные находятся по этому адресу. Это просто способ определения уникальных имён.
Любой может определить и использовать новые свойства SAX2 для своих читателей. Поддержка свойств не является обязательной.
Для установки или запроса свойств предоставляются следующие функции: QXmlReader::setProperty(), QXmlReader::property() и QXmlReader::hasProperty().
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.9/xml-sax.html