1. Знайомство з потоковим парсуванням
У Java історично склалися два підходи до роботи з XML.
Ми вже знаємо, що DOM (Document Object Model) будує дерево документа в пам’яті. Зручно переміщатися між елементами й редагувати їх, але для великих файлів це надто витратно: пам’ять швидко вичерпується.
Водночас SAX (Simple API for XML) обробляє файл послідовно й генерує події, коли зустрічає теги. Це економно щодо пам’яті, можна працювати з величезними документами. Але писати обробники незручно, а повернутися назад ієрархією неможливо.
StAX (Streaming API for XML) з’явився як компроміс. Він теж потоковий, як SAX, але дає програмісту більше контролю: ми самі «тягнемо» події з потоку, коли це потрібно. Такий підхід називають pull‑парсингом, і він дозволяє писати зрозуміліший і гнучкіший код.
Вступ до StAX
StAX (Streaming API for XML) — це сучасний потоковий парсер XML для Java, що з’явився у JDK 6+.
Головна ідея: pull‑парсинг («той, що тягне» парсер).
На відміну від SAX, де парсер сам викликає ваші методи (push‑модель), у StAX ви самі керуєте процесом:
Ви самі запитуєте у парсера: «Дай мені наступну подію!»
Аналогія:
SAX — це як телебачення: події «лиються» на вас, ви маєте реагувати.
StAX — це як сервіс, де ви самі натискаєте «наступне відео», коли готові.
Ключові класи StAX
Щоб працювати зі StAX, вам знадобляться два головні класи з пакета javax.xml.stream:
- XMLInputFactory — фабрика для створення парсерів.
- XMLStreamReader — потоковий парсер, який читає XML «шматочками».
Приклад базового коду:
import javax.xml.stream.*;
import java.io.FileInputStream;
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new FileInputStream("data.xml"));
while (reader.hasNext()) {
int event = reader.next();
// обробка події
}
reader.close();
2. Принцип роботи StAX: pull‑модель
У StAX ви самі керуєте читанням XML:
- Відкриваєте потік (наприклад, файл).
- Створюєте XMLStreamReader.
- У циклі викликаєте reader.next(), щоб отримати наступну подію.
- Перевіряєте тип події (START_ELEMENT, END_ELEMENT, CHARACTERS, тощо).
- Коли дійшли до потрібного місця — обробляєте дані.
- Закриваєте парсер.
Схема роботи:
У чому зручність?
- Ви самі вирішуєте, коли читати наступний елемент.
- Можна «зупинитися» в потрібному місці, обробити лише частину файлу.
- Не потрібно писати багато обробників, як у SAX.
3. Типи подій у StAX
Коли ви викликаєте reader.next(), парсер повертає тип події — ціле число (константа з інтерфейсу XMLStreamConstants). Ось основні типи подій:
- START_ELEMENT — початок XML‑елемента (<tag>).
- END_ELEMENT — кінець XML‑елемента (</tag>).
- CHARACTERS — текстовий вміст між тегами.
- END_DOCUMENT — кінець документа.
Приклад обробки подій:
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
String name = reader.getLocalName();
System.out.println("Початок елемента: " + name);
break;
case XMLStreamConstants.CHARACTERS:
String text = reader.getText().trim();
if (!text.isEmpty()) {
System.out.println("Текст: " + text);
}
break;
case XMLStreamConstants.END_ELEMENT:
System.out.println("Кінець елемента: " + reader.getLocalName());
break;
}
}
4. Корисні нюанси
Коли використовувати StAX?
StAX — ідеальний вибір, якщо:
- XML‑файл дуже великий (гігабайти), і ви не хочете завантажувати його повністю в пам’ять.
- Потрібно обробити лише частину документа (наприклад, знайти певний елемент і зупинитися).
- Потрібен простий і зрозумілий код: StAX простіший за SAX і не вимагає писати багато обробників.
Приклади завдань:
- Імпорт великого XML‑файлу з даними (наприклад, вивантаження з 1С, банківські виписки, каталоги товарів).
- Пошук і обробка лише потрібних елементів (наприклад, тільки <transaction> із мільйона записів).
- Перетворення XML «на льоту» (наприклад, фільтрація, агрегація).
Порівняння DOM, SAX і StAX
| Підхід | Пам’ять | Простота | Гнучкість | Коли використовувати |
|---|---|---|---|---|
| DOM | Висока (усе в пам’яті) | Дуже простий | Можна змінювати дерево | Малі/середні файли, коли потрібно редагувати XML |
| SAX | Мінімальна | Складно (обробники подій) | Лише читання, не можна повернутися назад | Дуже великі файли, проста обробка |
| StAX | Мінімальна | Середньо (pull‑модель) | Можна читати частинами, зручно зупинятися | Великі файли, коли потрібні гнучкість і простота |
StAX — золота середина:
— Не витрачає пам’ять, як DOM.
— Не вимагає складних обробників, як SAX.
— Дозволяє керувати процесом парсингу.
5. Приклад: читання великого XML‑файлу за допомогою StAX
Припустімо, у нас є файл "books.xml":
<library>
<book>
<title>Java для початківців</title>
<author>Іван Іванов</author>
</book>
<book>
<title>Просунута Java</title>
<author>Петро Петров</author>
</book>
<!-- ... багато книжок ... -->
</library>
Завдання: вивести всі назви книжок.
Код на StAX:
import javax.xml.stream.*;
import java.io.*;
public class StaxDemo {
public static void main(String[] args) throws Exception {
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new FileInputStream("books.xml"));
while (reader.hasNext()) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT && "title".equals(reader.getLocalName())) {
reader.next(); // переходимо до CHARACTERS
System.out.println("Книга: " + reader.getText());
}
}
reader.close();
}
}
Переваги:
- Не завантажуємо весь файл у пам’ять.
- Можна обробити хоч мільйон книжок — програма не «впаде».
6. Типові помилки під час роботи зі StAX
Помилка № 1: забули закрити парсер або потік. Завжди закривайте XMLStreamReader і потік (InputStream), щоб не було витоків ресурсів.
Помилка № 2: не перевіряєте тип події. Не всі події — це початок або кінець елемента. Перевіряйте тип події, інакше можна отримати порожні рядки або пропустити потрібні дані.
Помилка № 3: не враховуєте вкладеність елементів. Якщо структура XML складна (наприклад, книжки всередині розділів), стежте за поточним рівнем вкладеності, щоб не переплутати елементи.
Помилка № 4: використовуєте DOM для великих файлів. Якщо файл великий — не використовуйте DOM, інакше отримаєте OutOfMemoryError. Для великих файлів — лише StAX або SAX.
Помилка № 5: не обробляєте винятки. Робота з файлами та XML може викидати винятки (XMLStreamException, IOException). Обробляйте їх або прокидайте вище.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ