JavaRush /Курси /JAVA 25 SELF /StAX (Streaming API for XML) — потокове парсування

StAX (Streaming API for XML) — потокове парсування

JAVA 25 SELF
Рівень 47 , Лекція 2
Відкрита

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:

  1. Відкриваєте потік (наприклад, файл).
  2. Створюєте XMLStreamReader.
  3. У циклі викликаєте reader.next(), щоб отримати наступну подію.
  4. Перевіряєте тип події (START_ELEMENT, END_ELEMENT, CHARACTERS, тощо).
  5. Коли дійшли до потрібного місця — обробляєте дані.
  6. Закриваєте парсер.

Схема роботи:

flowchart TD A[Відкрити XMLStreamReader] --> B{hasNext?} B -- так --> C["next()"] C --> D{Тип події?} D -- START_ELEMENT --> E[Обробка початку елемента] D -- CHARACTERS --> F[Обробка тексту] D -- END_ELEMENT --> G[Обробка кінця елемента] D -- END_DOCUMENT --> H[Завершити] B -- ні --> H

У чому зручність?

  • Ви самі вирішуєте, коли читати наступний елемент.
  • Можна «зупинитися» в потрібному місці, обробити лише частину файлу.
  • Не потрібно писати багато обробників, як у 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). Обробляйте їх або прокидайте вище.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ