1. Введение
В этой статье мы будем сравнивать библиотеки Java XML и API.
Это вторая статья из серии о поддержке Java для XML, если вы хотите углубиться в поддержку XPath в Java, посмотрите предыдущую статью .
2. Обзор
Теперь мы углубимся в поддержку мира XML, и для этого мы начнем с максимально простого объяснения всех связанных с предметом инициалов.
В поддержке Java XML мы можем найти несколько определений API, каждое из которых имеет свои плюсы и минусы.
• SAX : это API синтаксического анализа на основе событий, он обеспечивает низкоуровневый доступ, эффективнее использует память и быстрее, чем DOM, поскольку не загружает все дерево документа в память, но не поддерживает навигацию, подобную предоставленной. с помощью XPath, хотя он более эффективен, его также сложнее использовать.
• DOM : это синтаксический анализатор на основе модели, который загружает документ древовидной структуры в память, поэтому у нас есть исходный порядок элементов, мы можем перемещаться по нашему документу в обоих направлениях, он предоставляет API для чтения и записи, он предлагает манипулирование XML и очень прост. прост в использовании, хотя цена - высокая нагрузка на ресурсы памяти.
• StAX : он предлагает простоту DOM и эффективность SAX, но ему не хватает некоторых функций, предоставляемых DOM, таких как манипулирование XML, и он позволяет нам перемещаться по документу только вперед.
• JAXB : он позволяет нам перемещаться по документу в обоих направлениях, он более эффективен, чем DOM, он позволяет преобразовывать XML в типы java и поддерживает работу с XML, но может анализировать только допустимый XML-документ.
Вы все еще можете найти некоторые ссылки на JAXP, но последний выпуск этого проекта датирован мартом 2013 года, и он практически мертв.
Таблица API-интерфейсов XML
3. XML
В этом разделе мы рассмотрим самые популярные реализации, чтобы мы могли протестировать реальные рабочие образцы и проверить различия между ними.
В следующих примерах мы будем работать с простым файлом XML с такой структурой:
<tutorials>
<tutorial tutId="01" type="java">
<title>Guava</title>
<description>Introduction to Guava</description>
<date>04/04/2016</date>
<author>GuavaAuthor</author>
</tutorial>
...
</tutorials>
4. ДОМ4Ж
Мы начнем с рассмотрения того, что мы можем сделать с DOM4J,
и для этого примера нам нужно добавить последнюю версию этой зависимости .
Это одна из самых популярных библиотек для работы с файлами XML
, поскольку она позволяет выполнять двунаправленное чтение, создавать новые документы и обновлять существующие.
DOM4J
может работать с DOM
, SAX
, XPath
и XLST
. SAX
поддерживается через JAXP
. ``
Давайте посмотрим, например, как мы можем выбрать фильтрацию элемента по заданному идентификатору.
SAXReader reader = new SAXReader();
Document document = reader.read(file);
List<Node> elements = document.selectNodes("//*[@tutId='" + id + "']");
return elements.get(0);
Класс SAXReader
отвечает за создание дерева DOM4J
из событий синтаксического анализа SAX .
Когда у нас есть org.dom4j.Document
, нам просто нужно вызвать нужный метод и передать ему выражение XPath в виде
строки.
Мы можем загрузить существующий документ, внести изменения в его содержимое, а затем обновить исходный файл.
for (Node node : nodes) {
Element element = (Element)node;
Iterator<Element> iterator = element.elementIterator("title");
while (iterator.hasNext()) {
Element title =(Element)iterator.next();
title.setText(title.getText() + " updated");
}
}
XMLWriter writer = new XMLWriter(
new FileWriter(new File("src/test/resources/example_updated.xml")));
writer.write(document);
writer.close();
В приведенном выше примере мы меняем содержимое каждого заголовка и создаем новый файл.
Обратите внимание, как просто получить каждый узел
заголовка в списке, вызвав elementIterator
и передав имя узла.
Как только мы изменим наш контент, мы будем использовать XMLWriter
, который берет дерево DOM4J
и форматирует его в поток как XML
.
Создание нового документа с нуля так же просто, как мы видим ниже.
Document document = DocumentHelper.createDocument();
Element root = document.addElement("XMLTutorials");
Element tutorialElement = root.addElement("tutorial").addAttribute("tutId", "01");
tutorialElement.addAttribute("type", "xml");
tutorialElement.addElement("title").addText("XML with Dom4J");
...
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(
new FileWriter(new File("src/test/resources/example_new.xml")), format);
writer.write(document);
writer.close();
DocumentHelper
предоставляет нам набор методов для использования DOM4J
, таких как createDocument
, который создает пустой документ, чтобы начать с ним работать.
Мы можем создать столько атрибутов или элементов, сколько нам нужно, с помощью методов, предоставляемых DOM4J
, и как только мы закончим наш документ, мы просто запишем его в файл, как мы делали это ранее в случае с обновлением.
5. ЖДОМ
Чтобы работать с JDOM,
мы должны добавить эту зависимость в наш файл pom.
Рабочий стиль JDOM
очень похож на стиль DOM4J
, поэтому мы рассмотрим всего пару примеров:
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(this.getFile());
Element tutorials = doc.getRootElement();
List<Element> titles = tutorials.getChildren("tutorial");
В приведенном выше примере мы извлекаем все элементы из корневого элемента очень простым способом, как мы можем сделать с DOM4J:
SAXBuilder builder = new SAXBuilder();
Document document = (Document) builder.build(file);
String filter = "//*[@tutId='" + id + "']";
XPathFactory xFactory = XPathFactory.instance();
XPathExpression<Element> expr = xFactory.compile(filter, Filters.element());
List<Element> node = expr.evaluate(document);
Опять же, здесь, в приведенном выше коде, у нас есть SAXBuilder
, создающий экземпляр Document
из заданного файла. Мы извлекаем элемент по его атрибуту tutId
, передавая выражение XPath
в XPathFactory
, предоставляемое JDOM2.
6. Стакс
Теперь мы увидим, как мы можем получить все элементы из нашего корневого элемента с помощью Stax API
. Stax
включен в JDK
, начиная с Java 6, поэтому вам не нужно добавлять какие-либо зависимости.
Во-первых, нам нужно создать класс Tutorial :
public class Tutorial {
private String tutId;
private String type;
private String title;
private String description;
private String date;
private String author;
// standard getters and setters
}
и тогда мы готовы следовать с:
List<Tutorial> tutorials = new ArrayList<>();
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLEventReader eventReader = factory.createXMLEventReader(new FileReader(this.getFile()));
Tutorial current;
while (eventReader.hasNext()) {
XMLEvent event = eventReader.nextEvent();
switch (event.getEventType()) {
case XMLStreamConstants.START_ELEMENT:
StartElement startElement = event.asStartElement();
String qName = startElement.getName().getLocalPart();
...
break;
case XMLStreamConstants.CHARACTERS:
Characters characters = event.asCharacters();
...
break;
case XMLStreamConstants.END_ELEMENT:
EndElement endElement = event.asEndElement();
// check if we found the closing element
// close resources that need to be explicitly closed
break;
}
}
В приведенном выше примере, чтобы помочь нам получить информацию, нам нужно было создать класс для хранения полученных данных.
Чтобы прочитать документ, мы объявили так называемые обработчики событий и использовали их для навигации по документу вперед. Помните, что реализации SAX не обеспечивают двунаправленную навигацию. Как вы можете видеть здесь, нужно проделать много работы только для того, чтобы получить простой список элементов.
7. ДЖАКСБ
JAXB
включен в JDK
, а также Xerces, поэтому для этого не требуется никаких дополнительных зависимостей.
С помощью JAXB
очень просто загружать, создавать и обрабатывать информацию из XML
-файла . ``
Нам просто нужно создать правильные объекты Java для привязки XML
, и все.
JAXBContext jaxbContext = JAXBContext.newInstance(Tutorials.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Tutorials tutorials = (Tutorials) jaxbUnmarshaller.unmarshal(this.getFile());
В приведенном выше примере мы загружаем наш файл XML
в наш объект, и оттуда мы можем обрабатывать все как обычную структуру Java;
Создать новый документ так же просто, как прочитать его, но сделать это в обратном порядке, как это сделано в приведенном ниже коде.
Во-первых, мы собираемся изменить наш учебный
класс, чтобы добавить аннотации JAXB к
геттерам
и сеттерам
:
public class Tutorial {
...
public String getTutId() {
return tutId;
}
@XmlAttribute
public void setTutId(String tutId) {
this.tutId = tutId;
}
...
@XmlElement
public void setTitle(String title) {
this.title = title;
}
...
}
@XmlRootElement
public class Tutorials {
private List<Tutorial> tutorial;
// standard getters and setters with @XmlElement annotation
}
С помощью @XmlRootElement
мы определяем, какой объект будет представлять корневой узел нашего документа, а затем мы используем @XmlAttribute
или @XmlElement
, чтобы определить, представляет ли этот атрибут атрибут узла или элемент документа.
Затем мы можем следовать:
Tutorials tutorials = new Tutorials();
tutorials.setTutorial(new ArrayList<>());
Tutorial tut = new Tutorial();
tut.setTutId("01");
...
tutorials.getTutorial().add(tut);
JAXBContext jaxbContext = JAXBContext.newInstance(Tutorials.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(tutorials, file);
Как видите, привязка XML-файла к объектам Java — самый простой способ работы с такими файлами.
8. Поддержка выражений XPath
Для создания сложных выражений XPath мы можем использовать Jaxen. Это библиотека XPath с открытым исходным кодом, которую можно адаптировать ко многим различным объектным моделям, включая DOM
, XOM
, DOM4J
и JDOM.
Мы можем создавать выражения XPath и компилировать их для многих поддерживаемых документов.
String expression = "/tutorials/tutorial";
XPath path = new DOMXPath(expression);
List result = path.selectNodes(xmlDocument);
Чтобы заставить его работать, нам нужно добавить эту зависимость в наш проект.
9. Заключение
Как видите, существует множество вариантов работы с XML
, в зависимости от требований вашего приложения вы можете работать с любым из них или вам придется выбирать между эффективностью и простотой.
Вы можете найти полные рабочие образцы для этой статьи в нашем git-репозитории здесь .