Русский учебник по XML

       

Что такое SAX


   Сегодня стандартным интерфейсом для большинства универсальных XML-анализаторов является событийно-ориентированное API SAX - Simple API for XML.

   Термин событийно-ориентированный является ключевым в этом определении и объясняет способ использования SAX. Каждый раз, когда при разборе XML документа анализатор оказывается в каком-то новом состоянии - обнаруживает какую-либо синтаксическую конструкцию XML-документа (элемент, символ, шаблон, и т.д.), фиксирует начало, конец объявлений элементов документа, просматривает DTD-правила или находит ошибку, он воспринимает его как произошедшее событие и вызывает внешнюю процедуру - обработчик этого события. Информация о содержимом текущей конструкции документа передается ему в качестве параметров функции. Обработчик события - это какой-то объект приложения, который выполняет необходимые для обработки полученной из XML информации действия и осуществляет таким образом непосредственный разбор содержимого. После завершения этой функции управление опять передается XML-анализатору и процесс разбора продолжается.

   Реализацией этого механизма в Java SAX 1.0 является библиотека классов org.xml.sax (их можно получить, например, с узла: , но обычно эти классы включаются в состав XML -анализатора). Наследуя клссы SAX-совместимого анализатора, мы получаем универсальный доступ к XML документу при помощи классов, содержимое и механизм использование которых приведено в соответствующем описании.

   Последовательный разбор XML-документа SAX-обработчиком обычно производится по следующей схеме (более подробное описание приведено ниже):

  • загрузить документ, установить обработчики событий, начать просмотр его содержимого (если есть DTD-описания, то - их разбор);
  • найдено начало документа (его корневой, самый первый элемент) - вызвать виртуальную функцию- обработчик события startDocument;
  • каждый раз, когда при разборе будет найден открывающий тэг элемента вызывается обработчик-функция startElement. В качестве параметров ей передаются название элемента и список его атрибутов;
  • найдено содержимое элемента - передать его соответствующему обработчику - characters, ignorableWhitespace,processingInstruction и т.д.;
  • если внутри текущего элемента есть подэлементы, то эта процедура повторяется;
  • найден закрывающий тэг элемента - обработать событие endElement();
  • найден закрывающий тэг корневого элемента -обработать событие endDocument;
  • если в процессе обработки были обнаружены ошибки, то анализатором вызываются обработчики предупреждений (warning), ошибок (error) и критических ошибок обработчика (fatalError).


    Ссылка на объект класса обработчика событий может передаваться объекту XML-анализатора при помощи следующих функций:

   parser.setDocumentHandler(event_class); // - обработчик событий документа

   parser.setEntityResolver(event_class); // - обработчик событий загрузки DTD-описаний

   parser.setDTDHandler(event_class); // - обработчик событий при анализе DTD-описаний

   parser.setErrorHandler(event_class); // - обработчик чрезвычайных ситуаций

   Здесь event_class - объект созданного нами ранее класса.

   Краткое описание некоторых из объектов-обработчиков событий приведено в следующей таблице:

   Объект DocumentHandler





startDocument()


Начало документа


endDocument()


Конец документа


startElement (String name, AttributeList atts)


Начало элемента. Функции передается название элемента(открывающий тэг) и список его атрибутов.


endElement (String name)


Конец элемента


characters (char[] cbuf, int start, int len)


Обработка массива текстовых символов


ignorableWhitespace (char[] cbuf, int start, int len)


Необрабатываемые символы


processingInstruction (String target, String data)


Обработка инструкций XML-анализатора)
   Объект ErrorHandler



warning (SAXParseException e)


Получение сообщения о "несерьезной" ошибке. Пдробная информация содержится в передаваемом объекте класса SAXParseException


error (SAXParseException e)


Сообщение об ошибке


fatalError (SAXParseException e)


Сообщение о критической ошибке
   Для демонстрции использования этих методов рассмотрим небольшой пример обработчика регистрационного XML-документа (его структура описана в примере 2 первого раздела статьи). Java-приложение выводит содержимое документа и информацию о его структуре, путь к документу задается в командной строке. Для компилирования потребуется JDK 1.1.4 и классы SAX, находящиеся либо в текущем пакете, либо вместе с другими классами в classes.zip. import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException;



import com.ibm.xml.parsers.DOMParser;

import org.xml.sax.Parser; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.AttributeList; import org.xml.sax.HandlerBase; import org.xml.sax.helpers.ParserFactory;

class saxParser extends HandlerBase{

private PrintWriter out;

private int elements; private int attributes; private int characters; private int ignorableWhitespace; private String url;

public saxParser(String url_str) {

url = url_str;

try { out = new PrintWriter(new OutputStreamWriter(System.out, "koi8-r")); } catch (UnsupportedEncodingException e) { }

}

//======================================================= // Обработчики событий. Методы интерфейса DocumentHandler //========================

// Начало документа public void startDocument() {

// Статистика elements = 0; attributes = 0; characters = 0; ignorableWhitespace = 0;

// Процессорные инструкции

out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");

}

// Конец документа public void endDocument() {

out.flush();

}

// Встретился открывающий тэг элемента //

public void startElement(String name, AttributeList attrs) {

elements++; if (attrs != null) { attributes += attrs.getLength(); }

// Печать тэга элемента вместе со списком его атрибутов, например, <elem id="48"> out.print('<'); out.print(name); if (attrs != null) { int len = attrs.getLength(); for (int i = 0; i < len; i++) { out.print(' '); out.print(attrs.getName(i)); out.print("=\""); out.print(attrs.getValue(i)); out.print('"'); } } out.println('>');

}

// Встретился закрывающий тэг элемента

public void endElement(String name) {

out.println("</"+name+">");

}

// Текстовые символы

public void characters(char ch[], int start, int length) {

characters += length;

out.println(new String(ch, start, length));

}

// Необрабатываемые символы(например, содержимое секции CDATA)

public void ignorableWhitespace(char ch[], int start, int length) {



characters(ch, start, length);

}

// Инструкции XML-процессору

public void processingInstruction (String target, String data) {

out.print("<?"); out.print(target); if (data != null && data.length() > 0) { out.print(' '); out.print(data); } out.print("?>");

}

//=================================================== // Методы интерфейса ErrorHandler //===============================

// Последнее предупреждение public void warning(SAXParseException ex) { System.err.println("Warning at "+ ex.getLineNumber()+" . "+ ex.getColumnNumber()+" - "+ ex.getMessage()); }

// Произошла ошибка public void error(SAXParseException ex) { System.err.println("Error at {"+ ex.getLineNumber()+" . "+ ex.getColumnNumber()+" - "+ ex.getMessage()); }

// Такие ошибки исправить уже нельзя public void fatalError(SAXParseException ex) throws SAXException { System.err.println("Fatal error at {"+ ex.getLineNumber()+" . "+ ex.getColumnNumber()+" - "+ ex.getMessage()); throw ex; }

//======================================================= // Вывести информацию о документе //===============================

public void printInfo() {

System.out.println();

System.out.println("Документ "+url+" был успешно обработан");

System.out.println("Элементов : "+elements); System.out.println("Атрибутов : "+attributes); System.out.println("Символов : "+characters);

}

}

//======================================================= // Обработка XML документа //========================

public class saxSample{

public static void main(String argv[]) {

try { saxParser sample = new saxParser(argv[0]);

Parser parser = ParserFactory.makeParser("com.ibm.xml.parsers.SAXParser"); parser.setDocumentHandler(sample); parser.setErrorHandler(sample);

parser.parse(argv[0]); sample.printInfo(); } catch (Exception e) { e.printStackTrace(System.err); }



}

}

Комментарии

   Первым шагом в процессе построения XML- обработчика является создание объекта из класса анализатора (в нашем случае это классы из паекета com.ibm.xml.parsers). Для этого можно использовать класс ParserFactory, входящий в org.xml.sax.helpers: import org.xml.sax.*; ... Parser parser = ParseFactory.createParser(); ...

   Затем следует определить обработчики возникающих в процессе разбора XML-документа событий. Приложению необязательно устанавливать все обработчики сразу - в классе HandlerBase все события могут обрабатываться "по умолчанию". Более подробную информацию по использованию SAX-анализаторов можно найти в примерах приложений в пакетах анализатора или на сервере www.megginson.com. Комментарии, файлы приложений и результатов их работы можно найти по адресу



Содержание раздела