Как читать и писать файлы XML с кодом

Хотите узнать, как читать и писать XML-файл из Java?

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

Java Standard Edition (SE)

включает в себя Java API для обработки XML (JAXP), это общий термин, охватывающий большинство аспектов обработки XML. Они включают:

  • DOM: Объектная модель документа включает в себя классы для работы с артефактами XML, такими как элемент, узел, атрибуты и т. Д. API DOM загружает полный документ XML в память для обработки, поэтому он не очень подходит для работы с большими файлами XML.
  • SAX: Simple API for XML — это управляемый событиями алгоритм чтения XML. Здесь XML обрабатывается путем запуска событий, найденных при чтении XML. Требования к памяти для использования этого метода низки, но работа с API более сложна, чем работа с DOM.
  • StAX: Streaming API для XML является недавним дополнением к XML APIs и обеспечивает высокопроизводительную потоковую фильтрацию, обработку и модификацию XML. Несмотря на то, что он избегает загрузки всего XML-документа в память, он предоставляет архитектуру типа pull, а не архитектуру, управляемую событиями, поэтому приложение легче кодировать и понимать, чем с помощью SAX API.

В этой статье мы используем DOM API продемонстрировать, как читать и писать файлы XML из Java. Мы рассмотрим два других API в следующих статьях.

Образец 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
...

Чтение XML-файла

Давайте рассмотрим основные шаги, необходимые для чтения XML-файла с использованием DOM API.

Первый шаг — получить экземпляр DocumentBuilder. Конструктор используется для разбора XML-документов. Для основного использования мы делаем это так:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
factory.setValidating(false);
DocumentBuilder builder = factory.newDocumentBuilder();

Теперь мы можем загрузить весь документ в память, начиная с корневого элемента XML. В нашем примере это элемент каталога.

File file = ...; // XML file to read
Document document = builder.parse(file);
Element catalog = document.getDocumentElement();

И это все, ребята! DOM API для чтения XML действительно прост. Теперь у вас есть доступ ко всему документу XML, начиная с его корневого элемента, каталога. Давайте теперь посмотрим, как с этим работать.

Использование DOM API

Теперь, когда у нас есть корневой элемент XML, мы можем использовать DOM API для извлечения интересных фрагментов информации.

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

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
}

Как вы находите конкретный дочерний элемент, учитывая родитель? Следующий статический метод возвращает первый соответствующий элемент, если он найден, или null. Как вы можете видеть, процедура включает в себя получение списка дочерних узлов и их циклический отбор, выбирая узлы элементов с указанным именем.

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 API обрабатывает текстовое содержимое внутри элемента как отдельный узел типа 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();
}

Вооружившись этими вспомогательными функциями, давайте теперь посмотрим на некоторый код для перечисления некоторой информации из нашего образца XML. Мы хотели бы показать подробную информацию для каждой книги, такую ​​как была бы доступна в каталоге книг.

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 Tranform API преобразовать данные XML. Мы используем этот API с преобразованием идентичности для генерации вывода.

В качестве примера, давайте добавим новый книга Элемент к образцу каталога представлен выше. Детали книги (такие как автор, название и т. Д.) Могут быть получены извне, возможно, из файла свойств или базы данных. Мы используем следующий файл свойств для загрузки данных.

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.

Первым шагом является анализ существующего XML-файла с использованием метода, представленного выше. Код также показан ниже.

File file = ...; // XML file to read
Document document = builder.parse(file);
Element catalog = document.getDocumentElement();

Мы загружаем данные из файла свойств, используя класс Properties, предоставляемый с Java. Код довольно прост и показан ниже.

String propsFile = ...;
Properties props = new Properties();
try (FileReader in = new FileReader(propsFile)) {
props.load(in);
}

Как только свойства загружены, мы извлекаем значения, которые мы хотим добавить, из файла свойств.

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 и добавляем значения в цикл.

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);

И вот как это делается. К элементу каталога теперь добавлен новый элемент книги. Все, что остается сейчас, это выписать обновленный XML.

Для написания XML нам нужен экземпляр Transformer, который создан, как показано ниже. Обратите внимание, что мы запрашиваем отступ выходного XML с помощью метода setOutputProperty ().

TransformerFactory tfact = TransformerFactory.newInstance();
Transformer tform = tfact.newTransformer();
tform.setOutputProperty(OutputKeys.INDENT, "yes");
tform.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");

Последний шаг в генерировании XML-вывода - применить преобразование. Результат отображается в выходном потоке System.out.

tform.transform(new DOMSource(document), new StreamResult(System.out));

Чтобы записать вывод непосредственно в файл, используйте следующее.

tform.transform(new DOMSource(document), new StreamResult(new File("output.xml")));

И это завершает эту статью о чтении и записи файлов XML с использованием DOM API.

Вы использовали DOM API в своих приложениях? Как это работает? Пожалуйста, дайте нам знать в комментариях ниже.

Ссылка на основную публикацию
Adblock
detector