API-интерфейс StAX Java для обработки XML предназначен для синтаксического анализа потоков XML, как и API SAX. Основные различия между ними:
- StAX — это «тянущий» API. SAX — это «push» API.
- StAX может выполнять чтение и запись XML. SAX может только читать XML.
API-интерфейс «Pull» и «Push»
SAX — это API в стиле push. Это означает, что синтаксический анализатор SAX просматривает XML и вызывает методы для предоставленного вами объекта обработчика. Например, когда SAX обнаруживает начало элемента XML, он вызывает startElement для объекта-обработчика. Он «выталкивает» информацию из XML в объект. Отсюда и название «push» в стиле API. Это также называется API, управляемым событиями. Ваш объект-обработчик уведомляется с помощью вызовов событий, когда в документе XML обнаруживается что-то интересное (элементы, тексты, комментарии и т. д.).
Синтаксический анализ SAX-парсера:
StAX — это API и означает, что нужно самим перемещать анализатор StAX от элемента к элементу в XML-файле, так же, как это делаете со стандартным Iterator или JDBC ResultSet. Затем можете получить доступ к информации XML через синтаксический анализатор для каждого такого «элемента», встречающегося в файле («элемент» = элементы, тексты, комментарии и т. д.).
Синтаксический анализ стиля парсера StAX показан здесь:
Фактически, StAX имеет два разных API для чтения:
- который больше всего похож на использование Iterator;
- который больше всего похож на использование ResultSet.
Они называются читателями «итератор» и «курсор».
Итак, в чем разница между ними?
Читатель итератора возвращает объект события XML из его вызовов nextEvent(). Из этого объекта вы можете увидеть, какой тип события встретили (элемент, текст, комментарий и т. д.). Этот элемент события является неизменным и может быть проанализирован в других частях приложения.
Вы также можете привязаться к более ранним объектам события при переходе к следующему. Это очень похоже на то, как используете обычный итератор при итерации по коллекции. Здесь вы просто перебираете события XML:
XMLEventReader reader = ...;
while(reader.hasNext()){
XMLEvent event = reader.nextEvent();
if(event.getEventType() == XMLEvent.START_ELEMENT){
StartElement startElement = event.asStartElement();
System.out.println(startElement.getName().getLocalPart());
}
//... more event types handled here...
}
Считыватель курсоров не возвращает события из своего вызова next(). Скорее этот вызов перемещает курсор к следующему «событию» в XML. Затем вы можете вызывать методы непосредственно на курсоре, чтобы получить больше информации о текущем событии.
Это очень похоже на то, как вы итерируете записи JDBC ResultSet и вызываете такие методы, как getString() или getLong(), чтобы получить значения из текущей записи, на которую указывает ResultSet:
XMLStreamReader streamReader = ...;
while(streamReader.hasNext()){
int eventType = streamReader.next();
if(eventType == XMLStreamReader.START_ELEMENT){
System.out.println(streamReader.getLocalName());
}
//... more event types handled here...
}
Итак, одно из основных отличий заключается в том, что можете использовать более ранние объекты событий XML при использовании API в стиле итераторов. Вы не можете сделать это при использовании API стиля курсора. Как только переместите курсор к следующему событию в потоке XML, у вас не будет информации о предыдущем событии. Это говорит в пользу использования API стиля итератора.
Тем не менее, API-интерфейс стиля курсора считается более эффективным с точки зрения памяти, чем стиля итератора. Итак, если приложению нужна абсолютная максимальная производительность, используйте API стиля курсора.
Реализация
На момент написания (Java 6) только интерфейсы StAX связывались с JDK. В Java нет встроенной реализации StAX. Но есть стандартная реализация, которую можно найти здесь: stax.codehaus.org/
