Simple API for XML
Simple API for XML (SAX) — это событийно-ориентированный программный интерфейс (API) для последовательного чтения и обработки XML-документов. В отличие от модели DOM (Document Object Model), которая загружает весь документ в память в виде древовидной структуры, SAX работает в режиме потока, разбирая XML по мере поступления данных и генерируя события (например, начало элемента, конец элемента, текстовое содержимое) для каждой части документа. SAX не создаёт модель документа в памяти, что делает его эффективным для обработки очень больших XML-файлов, которые не могут быть полностью загружены в оперативную память.
История
Разработка SAX началась в 1997 году в рамках проекта XML-DEV, списка рассылки, посвящённого обсуждению технологий XML. Основной целью было создание простого и лёгкого API для разбора XML, который бы не требовал значительных вычислительных ресурсов и был бы доступен для различных языков программирования. Первая версия, SAX1, была выпущена в мае 1998 года. Она определила базовые интерфейсы для обработчика содержимого (ContentHandler), обработчика ошибок (ErrorHandler) и другие.
Основным автором SAX считается Дэвид Меггинсон (David Megginson), который внёс значительный вклад в проектирование и документирование API. В 2000 году была выпущена версия SAX2, которая расширила функциональность, добавив поддержку пространств имён XML, фильтров и более гибкую систему обработки событий. SAX2 стал де-факто стандартом для событийно-ориентированного разбора XML в Java и других языках, хотя сам по себе SAX не является официальным стандартом какой-либо организации по стандартизации (например, W3C или ISO). Он остаётся общедоступной спецификацией, поддерживаемой сообществом.
Принцип работы
Событийная модель
SAX основан на модели «издатель-подписчик» (publisher-subscriber). Парсер SAX (например, Xerces или Crimson) выступает в роли издателя, а пользовательский код — в роли подписчика. В процессе разбора XML-документа парсер последовательно генерирует события, которые соответствуют структуре документа. Основные типы событий включают:
- startDocument() — начало документа.
- endDocument() — конец документа.
- startElement(String uri, String localName, String qName, Attributes atts) — начало элемента. Передаются URI пространства имён, локальное имя, полное имя (с префиксом) и атрибуты.
- endElement(String uri, String localName, String qName) — конец элемента.
- characters(char[] ch, int start, int length) — текстовое содержимое между элементами (символьные данные).
- ignorableWhitespace(char[] ch, int start, int length) — пробельные символы, которые могут быть проигнорированы.
- processingInstruction(String target, String data) — инструкции обработки (например,
<?xml-stylesheet ...?>). - error(SAXParseException e) — ошибка разбора (например, нарушение корректности XML).
Обработчики
Для обработки событий пользователь реализует интерфейсы-обработчики:
- ContentHandler — основной интерфейс для обработки содержимого документа (элементы, текст, инструкции).
- ErrorHandler — интерфейс для обработки ошибок разбора (предупреждения, ошибки, фатальные ошибки).
- DTDHandler — интерфейс для обработки объявлений из DTD (нотации и неразобранные сущности).
- EntityResolver — интерфейс для разрешения внешних сущностей (например, для перенаправления запросов к локальным ресурсам).
Потоковая обработка
SAX не требует загрузки всего документа в память. Парсер считывает XML-документ последовательно, байт за байтом, и генерирует события по мере обнаружения синтаксических конструкций. Это позволяет обрабатывать документы произвольного размера, ограниченного только доступной памятью для хранения текущего состояния (например, стека элементов). Пользовательский код может накапливать данные в структурах данных, но не обязан хранить весь документ.
Классификация
SAX относится к классу потоковых XML-парсеров (streaming XML parsers). В отличие от объектных моделей (DOM, JDOM, XOM), которые строят полное дерево документа в памяти, SAX предоставляет только последовательность событий. Существует также альтернативный потоковый API — StAX (Streaming API for XML), который, в отличие от SAX, является «тянущим» (pull-based): пользовательский код явно запрашивает следующее событие, а не получает его автоматически. SAX является «толкающим» (push-based) API: парсер сам вызывает методы обработчика.
Применение
SAX широко используется в сценариях, где требуется высокая производительность и низкое потребление памяти, особенно при работе с большими XML-документами. Основные области применения:
- Обработка больших XML-файлов (например, логов, экспортных данных из баз данных, файлов конфигурации).
- Потоковая передача данных (например, в веб-сервисах, где XML-документ передаётся по сети и обрабатывается по мере поступления).
- Фильтрация и трансформация XML (например, извлечение только определённых элементов или атрибутов).
- Валидация XML-документов (совместно с DTD или XML Schema).
- Создание собственных XML-инструментов (например, конвертеров, анализаторов).
Примеры
Пример на Java (SAX2)
```java import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory;
public class MySAXHandler extends DefaultHandler { @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.println("Начало элемента: " + qName); for (int i = 0; i < attributes.getLength(); i++) { System.out.println(" Атрибут: " + attributes.getQName(i) + " = " + attributes.getValue(i)); } }
@Override public void characters(char[] ch, int start, int length) throws SAXException { String text = new String(ch, start, length).trim(); if (!text.isEmpty()) { System.out.println(" Текст: " + text); } }
@Override public void endElement(String uri, String localName, String qName) throws SAXException { System.out.println("Конец элемента: " + qName); }
public static void main(String[] args) throws Exception { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.parse("example.xml", new MySAXHandler()); } } ```
Пример на Python (xml.sax)
```python import xml.sax
class MyHandler(xml.sax.ContentHandler): def startElement(self, name, attrs): print("Начало элемента:", name) for attr_name, attr_value in attrs.items(): print(" Атрибут:", attr_name, "=", attr_value)
def characters(self, content): content = content.strip() if content: print(" Текст:", content)
def endElement(self, name): print("Конец элемента:", name)
parser = xml.sax.make_parser() parser.setContentHandler(MyHandler()) parser.parse("example.xml") ```
Преимущества и недостатки
Преимущества
- Низкое потребление памяти: не требуется загружать весь документ в память.
- Высокая скорость: последовательный разбор без построения дерева.
- Простота реализации: для простых задач (например, извлечение одного поля) требуется минимум кода.
- Подходит для потоковой обработки: можно обрабатывать документы, которые ещё не полностью переданы по сети.
Недостатки
- Отсутствие произвольного доступа: нельзя обратиться к произвольному элементу документа без повторного разбора.
- Сложность обработки сложных структур: для построения внутреннего представления (например, дерева) требуется писать дополнительный код.
- Однонаправленность: разбор возможен только в одном направлении (от начала к концу).
- Неудобство для модификации: SAX не предназначен для изменения XML-документа; для этого обычно используют DOM или StAX.
Интересные факты
- SAX является одним из первых API для разбора XML, появившимся ещё до того, как XML стал широко распространён.
- Несмотря на появление более современных API (StAX, XPath, XSLT), SAX остаётся востребованным в задачах, где критична производительность и экономия памяти.
- Спецификация SAX не включает в себя реализацию парсера; она определяет только интерфейсы, которые должны быть реализованы разработчиками парсеров.
- В Java SAX входит в стандартную библиотеку (пакет
org.xml.saxиjavax.xml.parsers), что делает его доступным без установки дополнительных библиотек.
Источники
- David Megginson. SAX: The Simple API for XML. — 1998–2000.
- Спецификация SAX2: www.saxproject.org
- Elliotte Rusty Harold. XML Bible. — 2nd edition. — John Wiley & Sons, 2001. — Глава 17.
- Спецификация Java API for XML Processing (JAXP). — Oracle Corporation.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →