Интерфейс 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/archives/qt-5.11/xml-sax.html