Использование Java XML-обработчиков

Автор: Topol Понедельник, Апрель 16th, 2012 Нет комментариев

Рубрика: Программирование

Internet Explorer, несмотря на мощную встроенную поддержку XML, сегодня далеко не единственное средство, которое можно использовать для работы с новым языком. Обработкой XML документа на стороне клиента или сервера может также заниматься любой другой анализатор XML-документов, который конвертирует их в обычную HTML страницу или извлекает из нее информацию для других приложений.

Что такое XML Parser?

Любой XML-процессор, являясь, по сути, транслятором языка разметки, может быть разбит на несколько модулей, отвечающих за лексический, синтаксический и семантический анализ содержимого документа. Понятно, что если бы мы были вынуждены каждый раз писать все эти блоки самостоятельно, необходимость в XML как в таковом бы отпала — основное его преимущество, как уже упоминалось ранее, заключается в стандартном способе извлечения информации из документа. Синтаксически правильно составленный XML-документ может быть разобран любым универсальным XML анализатором, и нашему XML-обработчику остается лишь использовать полученные на его выходе «чистые» данные (прошедшие синтаксический анализ) — интерпретировать содержимое документа, в соответствии с его DTD-описанием или схемами данных.

Рис. 2 Иллюстрация механизма доступа к содержимому XML-документа при помощи интерфейсов анализатора

Конечно, синтаксический анализатор может быть довольно легко реализован и самостоятельно, например, в Perl, с его мощными возможностями обработки регулярных выражений. Но в общем случае такой «ручной» способ является довольно нетривиальной задачей, требующей некоторых усилий и является дополнительным источником ошибок. Поэтому применение универсальных XML-анализаторов может существенно облегчить жизнь разработчикам, тем более, что уже сегодня количество свободно доступных программ такого рода довольно велико.

В функции современного XML-процессора обычно входит получение общих сведений о документе, извлечение информации о его структуре и построения некоторой абстрактной объектной модели данных, представляющей эту структуру. По способу проверки разбираемых документов универсальные программы-анализаторы делятся на два типа: верифицирующие, способные обнаружить DTD-описания грамматики языка и использовать их для проверки документа на семантическую корректность; и неверифицирующие, не осуществляющие такой проверки.

Описывая разобранный XML-документ, универсальная программа-анализатор должна представить его структуру в виде упорядоченной модели данных, для доступа к которой используется какая-то станадртная, описанная в соответствующей спецификации библиотека классов — интерфейсов XML документа. На сегодняшний день существует два подхода к их построению: собыйтийный — Simple API for XML, SAX и объектно-ориентированный — DOM(Document Object Model). Рассмотрим их использование на конкретных примерах.

Что такое SAX

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

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

Реализацией этого механизма в Java SAX 1.0 является библиотека классов org.xml.sax (их можно получить, например, с узла: http://www.megginson.com/, но обычно эти классы включаются в состав 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();
}

// Печать тэга элемента вместе со списком его атрибутов, например,
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(«»);

}

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

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. Комментарии, файлы приложений и результатов их работы можно найти по адресу http://www.mrcpk.nstu.ru/

Источник: webcorp.ru

Оставить комментарий

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты