SAX (англ. «Simple API for XML») — способ последовательного чтения/записи XML-файлов.
Обычно SAX-парсеры требуют фиксированного количества памяти для своей работы, но не позволяют изменять содержимое документа. Всё, что делает SAX-парсер, это сообщает вызвавшему приложению о встретившихся распознанных элементах XML-разметки или о встретившихся ошибках. Связь парсера с вызывающим приложением, как правило, осуществляется посредством функций обратного вызова.
Реализации SAX-парсеров могут различаться, но в целом они устроены однотипно, примерно так, как показано ниже:
// ... На примере языка C++// Поток документаstruct Stream{ virtual xml_char pop_char() = 0; virtual bool has_data() = 0;};// Класс, которому парсер сообщает о найденных элементах разметкиstruct Callback{ virtual void doc_start() = 0; virtual void doc_end() = 0; virtual void element_start( string el_name ) = 0; virtual void element_end( string el_name ) = 0; virtual void attribute( string name, string value ) = 0; virtual void text_node( string txt ) = 0; // ...};// Сам парсер. -- Довольно сложный, чтобы его тут полностью записатьstruct Parser{ bool parse( Stream& xml, Callback& cb ); // ... };Использование:
struct MyFileStream : Stream { ... };struct MyCallback : Callback { ... };MyFileStream _stream( "some_file.xml" );MyCallback _cb;Parser parser;bool success = parser.parse( _stream, _cb );// Например, "some_file.xml" содержит следующий текст:// // bold text// // Тогда парсер вызовет методы класса "Callback" в следующем порядке:// _cb.doc_start();// _cb.element_start( "html" );// _cb.attribute( "lang", "en" );// _cb.element_start( "b" );// _cb.text_node( "bold text" );// _cb.element_end( "b" );// _cb.element_end( "html" );// _cb.doc_end();Применяются SAX-парсеры либо для быстрого поиска по XML-документам, либо во время построения DOM, либо для чтения XML-потоков большого объёма (когда построение DOM требует слишком большого объёма памяти).
SAX — событийный парсер XML. Он содержит очень похожую модель обработки событий на такую же модель в Java. К примеру, в аплете можно зарегистрировать обработчик события на клик мышкой, а в SAX можно зарегистрировать обработчик события на начало и конец тегов элементов, таких как и . В этом документе рассматривается XML парсер производства IBM. Он бесплатен и имеет общедоступные исходные тексты. Возьмём простой пример XML файла:
Soccer Ball 15.00 5 Параметр encoding="windows-1251" необходим для работы в кодировке Windows. Осуществим разбор XML-документа с помощью SAX в несколько шагов. Эти шаги выделены в коде примера.
- Регистрация парсера XML
- Создание экземпляра XMLReader
- Создание экземпляра класса, отвечающего за обработку событий SAX-а
- Подключение обработчика событий к экземпляру нашего XMLReader-а
- Разбор документа посредством передачи XMLReader-у XML файла. (В этом примере используется файл «order.xml», содержащий XML код, приведенный в начале статьи.)
В примере наш класс расширит DefaultHandler. DefaultHandler — это класс-адаптер, который позволит нам обрабатывать только те события SAX-а, которые нам нужны, а не реализовывать все его события.
package xml;import org.xml.sax.*;import org.xml.sax.helpers.DefaultHandler;public classSimpleSax extends DefaultHandler { private String currentElement = null; public static void main(String[] args) { try { //В JDK 5.0 введен этот парсер, и путь такой: com.sun.org.apache.xerces.internal.parsers.SAXParser. Class c = Class.forName("org.apache.xerces.parsers.SAXParser"); XMLReader reader = (XMLReader)c.newInstance(); SimpleSax ss = new SimpleSax(); reader.setContentHandler(ss); reader.parse("order.xml"); } catch(Exception e){System.out.println(e);} } public void startElement(String uri, String local_name, String raw_name, Attributes amap) throws SAXException { currentElement = local_name; System.out.println("start " + local_name + " found "); } public void endElement(String uri, String local_name, String raw_name) throws SAXException { System.out.println("end " + local_name + " found"); } public void startDocument() throws SAXException { System.out.println("start document"); } public void endDocument() throws SAXException { System.out.println("end document"); } public void characters(char[] ch, int start, int length) throws SAXException { String value = new String(ch,start,length); if (!Character.isISOControl(value.charAt(0))) { System.out.println("characters " + value + " found " + currentElement); } }}См. также
Литература
- David Brownell, SAX2, O’Reilly, ISBN 0-596-00237-8
- W. Scott Means, Michael A. Bodie: The Book of SAX, No Starch Press, ISBN 1-886411-77-8
Ссылки
- SAX homepage
- Top Ten SAX2 TipsАрхивная копия от 14 мая 2007 на Wayback Machine
- Интерфейсы для:
- Python
- JavaАрхивная копия от 6 февраля 2007 на Wayback Machine
- JavaScript