Гид по технологиям

Чтение и запись XML в Java

6 min read Java Обновлено 24 Apr 2026
Чтение и запись XML в Java
Чтение и запись XML в Java

Чтение и запись XML в Java — иллюстрация

XML-файлы используются для хранения и обмена структурированными данными. До широкого распространения JSON XML был основным форматом для описания, хранения и передачи структурированной информации. Сегодня XML встречается реже, но он по‑прежнему актуален в интеграции с унаследованными системами, конфигурацией серверов, спецификациях и документации.

Важно: DOM загружает весь документ в память. Для больших XML-файлов лучше рассмотреть SAX или StAX.

Требования для обработки XML в Java

Java SE включает API для обработки XML (JAXP). Главные подходы:

  • DOM: Document Object Model предоставляет классы для работы с элементами, узлами и атрибутами. DOM загружает весь документ в память — удобно для небольших и средних файлов.
  • SAX: Simple API for XML — событийный парсер. Низкое потребление памяти, но сложнее в коде, так как нужно реализовывать обработчики событий.
  • StAX: Streaming API for XML — потоковый парсер с pull‑архитектурой. Баланс между удобством и производительностью.

Для базовой работы в примерах ниже используются следующие пакеты:

import javax.xml.parsers.*;  
import javax.xml.transform.*;  
import org.w3c.dom.*;  

Подготовка примерного XML-файла

Пример XML-файла (фрагмент)

Для понимания примеров используем фрагмент XML (взятый из общедоступного образца):

  
  
    
    Gambardella, Matthew  
    XML Developer's Guide  
    Computer  
    44.95  
    2000-10-01  
    An in-depth look at creating applications  
      with XML.  
    
    
    Ralls, Kim  
...snipped...

Обратите внимание: имена тегов чувствительны к регистру и должны совпадать в коде и в XML.

Чтение XML с помощью DOM API: базовые шаги

  1. Создайте фабрику и билдера DocumentBuilder:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
DocumentBuilder builder = factory.newDocumentBuilder();
  1. Загрузите документ и получите корневой элемент (в примере это ):
// XML file to read  
File file = "";  
Document document = builder.parse(file);  
Element catalog = document.getDocumentElement();  

После этого у вас есть доступ ко всему XML-документу, начиная с корня.

Извлечение данных через DOM API

DOM предоставляет доступ к точкам дерева. Частые задачи: получить список элементов, отфильтровать текстовые узлы, найти первый вложенный элемент с данным именем.

Пример получения всех детей элемента catalog и фильтрации только элементов:

NodeList books = catalog.getChildNodes();  
  
for (int i = 0, ii = 0, n = books.getLength() ; i < n ; i++) {  
  Node child = books.item(i);  
  
  if ( child.getNodeType() != Node.ELEMENT_NODE )  
    continue;  
  
  Element book = (Element)child;  
  // work with the book Element here  
}  

Полезная утилита: найти первый вложенный элемент с заданным именем:

static private Node findFirstNamedElement(Node parent, String tagName)  
{  
  NodeList children = parent.getChildNodes();  
  
  for (int i = 0, in = children.getLength() ; i < in ; i++) {  
    Node child = children.item(i);  
  
    if (child.getNodeType() != Node.ELEMENT_NODE)  
      continue;  
  
    if (child.getNodeName().equals(tagName))  
      return child;  
  }  
  
  return null;  
}  

DOM рассматривает текст внутри элемента как узлы типа TEXT_NODE. Часто текст разбит на несколько соседних текстовых узлов, поэтому удобна функция для извлечения всего текста элемента:

static private String getCharacterData(Node parent)  
{  
  StringBuilder text = new StringBuilder();  
  
  if ( parent == null )  
    return text.toString();  
  
  NodeList children = parent.getChildNodes();  
  
  for (int k = 0, kn = children.getLength() ; k < kn ; k++) {  
    Node child = children.item(k);  
  
    if (child.getNodeType() != Node.TEXT_NODE)  
      break;  
  
    text.append(child.getNodeValue());  
  }  
  
  return text.toString();  
}  

Пример кода, собирающего информацию о книгах и печатающего её:

NodeList books = catalog.getChildNodes();  
  
for (int i = 0, ii = 0, n = books.getLength() ; i < n ; i++) {  
  Node child = books.item(i);  
  
  if (child.getNodeType() != Node.ELEMENT_NODE)  
    continue;  
  
  Element book = (Element)child;  
  ii++;  
  
  String id = book.getAttribute("id");  
  String author = getCharacterData(findFirstNamedElement(child, "author"));  
  String title = getCharacterData(findFirstNamedElement(child, "title"));  
  String genre = getCharacterData(findFirstNamedElement(child, "genre"));  
  String price = getCharacterData(findFirstNamedElement(child, "price"));  
  String pubdate = getCharacterData(findFirstNamedElement(child, "pubdate"));  
  String descr = getCharacterData(findFirstNamedElement(child, "description"));  
  
  System.out.printf("%3d. book id = %s\n" +  
    " author: %s\n" +  
    " title: %s\n" +  
    " genre: %s\n" +  
    " price: %s\n" +  
    " pubdate: %s\n" +  
    " descr: %s\n",  
    ii, id, author, title, genre, price, pubdate, descr);  
}  

Вывод будет содержать подробную информацию по каждой книге.

Парсинг XML в Java: код и вывод

Запись XML с помощью Transform API

Java предоставляет XML Transform API. Часто используют т.н. identity‑преобразование, чтобы сериализовать DOM‑дерево обратно в XML.

Рассмотрим пример: добавим новую запись в существующий .

Данные можно получить из properties-файла. Пример properties:

id=bk113  
author=Jane Austen  
title=Pride and Prejudice  
genre=Romance  
price=6.99  
publish_date=2010-04-01  
description="It is a truth universally acknowledged, that a single man in possession of a good fortune must be in want of a wife." So begins Pride and Prejudice, Jane Austen's witty comedy of manners-one of the most popular novels of all time-that features splendidly civilized sparring between the proud Mr. Darcy and the prejudiced Elizabeth Bennet as they play out their spirited courtship in a series of eighteenth-century drawing-room intrigues.  

Шаги:

  1. Спарсить существующий XML, как показано выше:
File file = ...; // XML file to read  
Document document = builder.parse(file);  
Element catalog = document.getDocumentElement();  
  1. Загрузить properties:
String propsFile = "";  
Properties props = new Properties();  
  
try (FileReader in = new FileReader(propsFile)) {  
  props.load(in);  
}  
  1. Получить значения и создать элемент book с дочерними элементами:
String id = props.getProperty("id");  
String author = props.getProperty("author");  
String title = props.getProperty("title");  
String genre = props.getProperty("genre");  
String price = props.getProperty("price");  
String publish_date = props.getProperty("publish_date");  
String descr = props.getProperty("description");  

Element book = document.createElement("book");  
book.setAttribute("id", id);  

List elnames = Arrays.asList("author", "title", "genre", "price",  
  "publish_date", "description");  
  
for (String elname : elnames) {  
  Element el = document.createElement(elname);  
  Text text = document.createTextNode(props.getProperty(elname));  
  el.appendChild(text);  
  book.appendChild(el);  
}  
  
catalog.appendChild(book);  
  1. Сериализовать и записать XML:
TransformerFactory tfact = TransformerFactory.newInstance();  
Transformer tform = tfact.newTransformer();  
tform.setOutputProperty(OutputKeys.INDENT, "yes");  
tform.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");

// на консоль
tform.transform(new DOMSource(document), new StreamResult(System.out));

// или в файл
tform.transform(new DOMSource(document), new StreamResult(new File("output.xml")));

Теперь документ сохранён с добавленной записью .

Когда DOM не подходит

  • Очень большие XML-файлы (десятки мегабайт и более): DOM потребляет много памяти, так как загружает дерево целиком.
  • Потоковые сценарии обработки, где данные приходят по сети и должны обрабатываться по мере поступления.

Альтернатива: SAX или StAX. SAX хорошо для простых задач чтения при ограниченной памяти. StAX удобен, когда нужен контроль порядка событий и частичное изменение потока.

Альтернативные подходы и их применимость

  • SAX: низкая нагрузка на память, хорош для чтения. Событийная модель затрудняет случайный доступ и модификацию дерева.
  • StAX: pull‑парсер. Удобнее в коде, чем SAX. Позволяет читать и писать одновременно, хорошо подходит для потоковой трансформации.
  • XPath вместе с DOM или StAX: поиск узлов по выражениям XPath упрощает выборку нужных элементов.
  • Библиотеки третьих сторон (например, JAXB, Jackson для XML, XOM, dom4j): дают более удобные API, маппинг на POJO и дополнительные функции.

Пошаговая методология (микро‑SOP)

  1. Оцените размер и характер XML (разовый файл, поток, большой объём).
  2. Выберите модель: DOM (удобно редактировать), StAX/SAX (производительно), или библиотеку‑мэппер (удобство работы с объектами).
  3. Напишите тесты: парсинг, сериализация, регрессия структуры.
  4. При изменении XML сохраняйте исходную кодировку и префиксы namespace, если они важны.
  5. Обрабатывайте ошибки: парсинг, I/O, валидность схемы (XSD) — логируйте и возвращайте понятные сообщения.

Шпаргалка — быстрое руководство

  • Создать DocumentBuilder: DocumentBuilderFactory.newInstance().newDocumentBuilder()
  • Спарсить файл: builder.parse(new File(“path.xml”))
  • Получить корень: document.getDocumentElement()
  • Добавить элемент: document.createElement(“tag”) и parent.appendChild(newNode)
  • Добавить текст: document.createTextNode(“text”)
  • Сериализация: TransformerFactory.newInstance().newTransformer().transform(…)

Контрольные списки по ролям

Разработчик:

  • Проверить соответствие имён тегов и атрибутов.
  • Обработать null‑значения и отсутствующие теги.
  • Написать модульные тесты на парсинг и сериализацию.

Тестировщик:

  • Проверить поведение на пустом/неполном/невалидном XML.
  • Замерить потребление памяти и время обработки для реального объёма данных.
  • Проверить кодировку и спецсимволы.

Оператор/DevOps:

  • Автоматизировать миграцию и бэкапы XML-файлов перед изменением.
  • Настроить ротацию логов и мониторинг ошибок парсинга.

Частые ошибки и как их избежать

  • Несоответствие имён тегов в коде и в XML. Решение: централизуйте имена тегов в константах.
  • Игнорирование пространств имён (namespaces). Если XML использует namespace, включите соответствующую обработку в DocumentBuilderFactory.
  • Ожидание единственного текстового узла, когда их несколько. Используйте getCharacterData или объединяйте соседние TEXT_NODE.

Важно: всегда валидируйте входные XML‑файлы, если приложение требует строгой структуры (например, с XSD).

Ментальные модели и эвристики

  • «DOM = дерево в памяти»: удобно читать и модифицировать, но дорого по памяти.
  • «SAX = события»: хорош для однонаправленного прохода без модификации дерева.
  • «StAX = контроль»: удобный компромисс для потоковой обработки с возможностью выборочного чтения/записи.

Фактбокс — ключевые ориентиры

  • DOM: подходит для файлов до нескольких мегабайт в типичных JVM. При сотнях мегабайт возможны OOME.
  • SAX/StAX: используются для потоков и больших файлов. StAX проще в коде, чем SAX.
  • Transformer: удобен для сериализации DOM в красивый XML с отступами.

(Значения приведены качественно; конкретные пороги зависят от JVM, настроек памяти и структуры XML.)

Советы по совместимости и миграции

  • При миграции с устаревших библиотек проверьте поддержку XML namespace и чтение/запись BOM/кодировок.
  • Если ваша система использует XSD, добавьте этап валидации перед использованием данных.
  • Для интеграции с REST/JSON подумайте о преобразовании XML↔JSON в отдельном слое, чтобы минимизировать количество компонентов, работающих напрямую с XML.

Критерии приёмки

  • Приложение корректно читает все обязательные теги и атрибуты из тестового XML.
  • При добавлении новой записи (book) документ сохраняется и читается обратно без потери данных.
  • Обработка невалидного XML не приводит к необработанным исключениям; ошибки логируются.
  • Тесты покрытия включают сценарии с отсутствующими тегами, дополнительными неизвестными тегами и разными кодировками.

Заключение

Парсинг и модификация XML в Java — практический навык, который пригодится при интеграции с унаследованными системами и при работе с конфигурациями. DOM и Transform API удобны для задач, где требуется удобное обращение к дереву и простая сериализация. Для больших данных и потоковой обработки рассмотрите StAX или SAX.

Ключевые шаги: выбрать правильную модель (DOM/SAX/StAX), централизовать имена тегов, покрыть код тестами и обработать ошибки ввода.

Сводка:

  • DOM удобен для редактирования и небольших/средних документов.
  • StAX/SAX — для больших или потоковых данных.
  • Transformer позволяет легко записывать отформатированный XML.

Если нужно, могу добавить пример с использованием StAX или показать, как применять XPath для выборки узлов.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

KDE Connect: связать Android и Linux
Linux

KDE Connect: связать Android и Linux

Как перейти от новичка к фотографу среднего уровня
Фотография

Как перейти от новичка к фотографу среднего уровня

Уведомления о камере в Windows 11
Конфиденциальность

Уведомления о камере в Windows 11

Ускорение передачи данных на внешние диски
Windows

Ускорение передачи данных на внешние диски

Родительский контроль Xbox: настройка через Family Settings
Руководство

Родительский контроль Xbox: настройка через Family Settings

Поиск песни по тексту в Apple Music
Музыка

Поиск песни по тексту в Apple Music