XMLStreamReader.next(): примеры (JAVA)
XMLStreamReader.next(): intОписание метода XMLStreamReader.next()
Метод next() интерфейса javax.xml.stream.XMLStreamReader используется для перехода к следующему событию в потоке XML. Он не принимает аргументов и возвращает целое число (int), которое соответствует типу текущего события после перехода. Типы событий определены как константы в классе XMLStreamConstants:
- START_ELEMENT (1) – начало элемента
- END_ELEMENT (2) – конец элемента
- CHARACTERS (4) – текст
- CDATA (12) – секция CDATA
- COMMENT (5) – комментарий
- SPACE (6) – пробельные символы
- PROCESSING_INSTRUCTION (3) – инструкция обработки
- ENTITY_REFERENCE (9) – ссылка на сущность
- DTD (11) – DTD
- END_DOCUMENT (8) – конец документа
Метод применяется для последовательного чтения XML-документа. Перед первым вызовом next() состояние reader соответствует константе START_DOCUMENT (7). Каждый вызов перемещает указатель на одно событие вперёд. Если достигнут конец документа и попытаться вызвать next() повторно, будет выброшено исключение java.util.NoSuchElementException.
Метод может выбросить XMLStreamException при ошибках парсинга или ввода-вывода.
Примеры использования XMLStreamReader.next()
Пример 1: Подсчёт элементов
import javax.xml.stream.*;
import java.io.*;
public class Example1 {
public static void main(String[] args) throws Exception {
String xml = "<root><a/><b>text</b></root>";
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(xml));
int count = 0;
while (reader.hasNext()) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
count++;
}
}
reader.close();
System.out.println("Стартовых элементов: " + count);
}
}Стартовых элементов: 2
Пример 2: Вывод всех событий с типом
import javax.xml.stream.*;
import java.io.*;
public class Example2 {
public static void main(String[] args) throws Exception {
String xml = "<?xml version='1.0'?><doc id='1'>Hello<!-- comment --></doc>";
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(xml));
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
System.out.println("START_ELEMENT: " + reader.getLocalName());
break;
case XMLStreamConstants.END_ELEMENT:
System.out.println("END_ELEMENT: " + reader.getLocalName());
break;
case XMLStreamConstants.CHARACTERS:
System.out.println("CHARACTERS: '" + reader.getText() + "'");
break;
case XMLStreamConstants.COMMENT:
System.out.println("COMMENT");
break;
case XMLStreamConstants.END_DOCUMENT:
System.out.println("END_DOCUMENT");
break;
}
}
reader.close();
}
}START_ELEMENT: doc CHARACTERS: 'Hello' COMMENT END_ELEMENT: doc END_DOCUMENT
Похожие функции в Java
XMLStreamReader.nextTag() – переходит к следующему стартовому или конечному тегу, пропуская пробельные символы и комментарии. Полезно, когда нужно быстро добраться до элемента, игнорируя незначимые события. В отличие от next(), nextTag() выбрасывает XMLStreamException, если следующее событие не является START_ELEMENT или END_ELEMENT.
SAXParser (пакет org.xml.sax) предлагает событийно-ориентированный подход с колбэками, где не нужно вручную вызывать next(). Удобен для больших документов, но сложнее в управлении состоянием.
DocumentBuilder (DOM) – загружает весь документ в память, затем доступ через методы getChildNodes() и т.д. Не требует итерации событиями, но потребляет много памяти.
Выбор между next() и nextTag() зависит от необходимости обрабатывать пробелы, комментарии и другие события. Для потокового чтения с детальным контролем используется next().
Альтернативы в других языках программирования
PHP
XMLReader::read() – аналог next(). Возвращает true при успешном чтении, устанавливает тип узла в свойство nodeType.
<?php
$xml = '<root><item>val</item></root>';
$reader = new XMLReader();
$reader->XML($xml);
while ($reader->read()) {
echo $reader->nodeType . ": " . $reader->name . "\n";
}
?>1: root 1: item 3: val 15: item 15: root
JavaScript
DOMParser не имеет прямого аналога. Для потокового чтения можно использовать XMLHttpRequest с responseXML или сторонние SAX-библиотеки.
const parser = new DOMParser();
const xmlDoc = parser.parseFromString('<root><item/></root>', 'text/xml');
const items = xmlDoc.getElementsByTagName('item');
console.log(items.length);1
Python
xml.etree.ElementTree.iterparse() порождает события start, end и т.д. Похож на SAX.
import xml.etree.ElementTree as ET
xml = '<root><a>text</a></root>'
events = [(event, elem.tag) for event, elem in ET.iterparse(xml, events=('start', 'end'))]
print(events)[('start', 'root'), ('start', 'a'), ('end', 'a'), ('end', 'root')]C#
XmlReader.Read() – прямой аналог. Возвращает bool, далее NodeType.
using System.Xml;
string xml = "<root><item>val</item></root>";
using (XmlReader reader = XmlReader.Create(new StringReader(xml)))
{
while (reader.Read())
{
Console.WriteLine(reader.NodeType + ": " + reader.Name);
}
}Element: root Element: item Text: EndElement: item EndElement: root
Lua
luaXML – библиотека с методом xml:next(), возвращающим тип события.
local xml = require("xml")
local doc = xml.parse("<root><a/></root>")
for event, elem in doc:next() do
print(event, elem)
endstart root start a end a end root
Go
encoding/xml.Decoder.Token() возвращает токен (StartElement, CharData, EndElement) или ошибку.
package main
import (
"encoding/xml"
"fmt"
"strings"
)
func main() {
xmlStr := `<root><item>val</item></root>`
decoder := xml.NewDecoder(strings.NewReader(xmlStr))
for {
t, err := decoder.Token()
if err != nil { break }
switch se := t.(type) {
case xml.StartElement:
fmt.Println("StartElement:", se.Name.Local)
case xml.EndElement:
fmt.Println("EndElement:", se.Name.Local)
case xml.CharData:
fmt.Println("CharData:", string(se))
}
}
}StartElement: root StartElement: item CharData: val EndElement: item EndElement: root
Kotlin
Использует Java API, поэтому XMLStreamReader.next() доступен напрямую. Отличий нет.
Типичные ошибки при использовании XMLStreamReader.next()
1. Вызов после достижения конца документа
XMLStreamReader reader = ...;
while (reader.hasNext()) {
reader.next();
}
// reader.hasNext() == false, но можно случайно вызвать reader.next() ещё раз
// reader.next(); // NoSuchElementExceptionException in thread "main" java.util.NoSuchElementException at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:570)
2. Игнорирование проверки состояния перед вызовом next()
Если не вызвать hasNext() перед next(), в конце документа будет исключение.
3. Попытка повторного использования закрытого reader
reader.close();
reader.next(); // XMLStreamExceptionjavax.xml.stream.XMLStreamException: Stream closed
4. Неправильная обработка типов событий
Например, вызов getLocalName() на событии CHARACTERS приводит к IllegalStateException. Необходимо всегда проверять тип события перед вызовом соответствующих методов.
int event = reader.next();
String name = reader.getLocalName(); // если event == CHARACTERS, будет исключениеjava.lang.IllegalStateException
Изменения в последних версиях Java
Метод XMLStreamReader.next() является частью спецификации StAX (JSR 173), которая входит в стандартную библиотеку Java начиная с Java 6 (в составе пакета javax.xml.stream). В последующих версиях Java (8, 9, 11, 17) поведение метода не претерпело существенных изменений. Однако в Java 9 была проведена модуляризация, и пакет javax.xml.stream был помещён в модуль java.xml. Это может потребовать указания модуля в module-info.java для модульных проектов. В остальном метод остаётся стабильным.
Расширенные примеры использования XMLStreamReader.next()
Пример 1: Обработка вложенных элементов с отслеживанием глубины
import javax.xml.stream.*;
import java.io.*;
public class AdvExample1 {
public static void main(String[] args) throws Exception {
String xml = "<root><level1><level2 attr='x'/></level1></root>";
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(xml));
int depth = 0;
while (reader.hasNext()) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
depth++;
System.out.println("Открытие " + reader.getLocalName() + " на глубине " + depth);
for (int i = 0; i < reader.getAttributeCount(); i++) {
System.out.println(" Атрибут: " + reader.getAttributeLocalName(i) + "=" + reader.getAttributeValue(i));
}
} else if (event == XMLStreamConstants.END_ELEMENT) {
System.out.println("Закрытие " + reader.getLocalName() + " на глубине " + depth);
depth--;
}
}
reader.close();
}
}Открытие root на глубине 1 Открытие level1 на глубине 2 Открытие level2 на глубине 3 Атрибут: attr=x Закрытие level2 на глубине 3 Закрытие level1 на глубине 2 Закрытие root на глубине 1
Пример 2: Пропуск неинтересующих элементов
import javax.xml.stream.*;
import java.io.*;
public class AdvExample2 {
public static void main(String[] args) throws Exception {
String xml = "<data><a>1</a><skip>не нужно</skip><b>2</b></data>";
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(xml));
while (reader.hasNext()) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT && "skip".equals(reader.getLocalName())) {
// пропускаем содержимое элемента skip до его закрытия
while (reader.hasNext()) {
int ev = reader.next();
if (ev == XMLStreamConstants.END_ELEMENT && "skip".equals(reader.getLocalName())) {
break;
}
}
continue;
}
if (event == XMLStreamConstants.CHARACTERS) {
System.out.println("Текст: " + reader.getText());
}
}
reader.close();
}
}Текст: 1 Текст: 2
Пример 3: Работа с пространствами имён
import javax.xml.stream.*;
import java.io.*;
public class AdvExample3 {
public static void main(String[] args) throws Exception {
String xml = "<ns:root xmlns:ns='http://example.com'>" +
"<ns:child ns:attr='5'>text</ns:child></ns:root>";
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(xml));
while (reader.hasNext()) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
System.out.println("Элемент: " + reader.getLocalName() +
" namespace: " + reader.getNamespaceURI());
for (int i = 0; i < reader.getAttributeCount(); i++) {
System.out.println(" Атрибут: " + reader.getAttributeLocalName(i) +
" namespace: " + reader.getAttributeNamespace(i));
}
}
}
reader.close();
}
}Элемент: root namespace: http://example.com Элемент: child namespace: http://example.com Атрибут: attr namespace: http://example.com
Пример 4: Обработка CDATA и комментариев
import javax.xml.stream.*;
import java.io.*;
public class AdvExample4 {
public static void main(String[] args) throws Exception {
String xml = "<root><![CDATA[some & chars]]>" +
"<!-- comment --></root>";
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(xml));
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.CDATA:
System.out.println("CDATA: '" + reader.getText() + "'");
break;
case XMLStreamConstants.COMMENT:
System.out.println("COMMENT: " + reader.getText());
break;
}
}
reader.close();
}
}CDATA: 'some & chars' COMMENT: comment
джава XMLStreamReader.next() function comments
- джава XMLStreamReader.next() - аргументы и возвращаемое значение
- Функция java XMLStreamReader.next() - описание
- XMLStreamReader.next() - примеры
- XMLStreamReader.next() - похожие методы на java
- XMLStreamReader.next() на javascript, c#, python, php
- XMLStreamReader.next() изменения java
- Примеры XMLStreamReader.next() на джава