SAX

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" содержит следующий текст: // <html lang="en"> //   <b>bold text</b> // </html>  // Тогда парсер вызовет методы класса "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 можно зарегистрировать обработчик события на начало и конец тегов элементов, таких как <name> и </name>. В этом документе рассматривается XML парсер производства IBM. Он бесплатен и имеет общедоступные исходные тексты. Возьмём простой пример XML файла:

 <?xml version="1.0" encoding="windows-1251"?>  <order>    <item>      <name>Soccer Ball</name>      <price>15.00</price>      <quantity>5</quantity>    </item>  </order> 

Параметр 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 class SimpleSax 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);    }   } } 

Литература

[править | править код]