Поддержка XML-библиотек в Java

Поддержка XML-библиотек в Java

1. Вступление

В этой статье мы будем сравнивать библиотеки Java XML и API.

Это вторая статья из серии о поддержке XML в Java. Если вы хотите глубже изучить поддержку XPath в Java, взгляните наthe previous article.

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 года, и он практически мертв.

XML Apis Table

Таблица XML API

3. XML

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

В следующих примерах мы будем работать с простым XML-файлом со структурой, подобной этой:


    
        Guava
        Introduction to Guava
        04/04/2016
        GuavaAuthor
    
    ...

4. dOM4J

Мы собираемся начать с того, что посмотрим, что мы можем сделать сDOM4J, и для этого примера нам нужно добавить последнюю версию этогоdependency.

Это одна из самых популярных библиотек для работы с файламиXML, поскольку она позволяет нам выполнять двунаправленное чтение, создавать новые документы и обновлять существующие.

DOM4J может работать сDOM,SAX,XPath иXLST. SAX поддерживается черезJAXP. __

Давайте посмотрим, например, как мы можем выбрать фильтрацию элемента по заданному идентификатору.

SAXReader reader = new SAXReader();
Document document = reader.read(file);
List elements = document.selectNodes("//*[@tutId='" + id + "']");
return elements.get(0);

КлассSAXReader отвечает за создание дереваDOM4J из событий синтаксического анализаSAX. Как только у нас естьorg.dom4j.Document, нам просто нужно вызвать необходимый метод и передать ему выражениеXPath какString.

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

for (Node node : nodes) {
    Element element = (Element)node;
    Iterator 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();

В приведенном выше примере мы меняем содержание каждого заголовка и создаем новый файл.

Обратите внимание, как просто получитьnode каждого заголовка в списке, вызвавelementIterator и передав имяnode.

Как только мы изменим наш контент, мы будем использовать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

Чтобы работать сJDOM,, мы должны добавить этотdependency в наш pom.

Стиль работыJDOM’s очень похож на стиль работыDOM4J’s, поэтому мы рассмотрим всего несколько примеров:

SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(this.getFile());
Element tutorials = doc.getRootElement();
List titles = tutorials.getChildren("tutorial");

В приведенном выше примере мы получаем все элементы из корневого элемента очень простым способом, как мы можем сделать сDOM4J:

SAXBuilder builder = new SAXBuilder();
Document document = (Document) builder.build(file);
String filter = "//*[@tutId='" + id + "']";
XPathFactory xFactory = XPathFactory.instance();
XPathExpression expr = xFactory.compile(filter, Filters.element());
List node = expr.evaluate(document);

Опять же, здесь, в приведенном выше коде, у нас естьSAXBuilder, создающий экземплярDocument из заданного файла. Мы получаем элемент по его атрибутуtutId, передавая выражениеXPath вXPathFactory, предоставленноеJDOM2.

6. StAX

Теперь мы посмотрим, как мы можем получить все элементы из нашего корневого элемента, используя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 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

JAXB включен вJDK, а также в Xerces, для него не требуется никаких дополнительных зависимостей.

Загружать, создавать и обрабатывать информацию из файлаXML очень просто, используяJAXB.

Нам просто нужно создать правильные объекты Java для привязкиXML, и все.

JAXBContext jaxbContext = JAXBContext.newInstance(Tutorials.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Tutorials tutorials = (Tutorials) jaxbUnmarshaller.unmarshal(this.getFile());

В приведенном выше примере мы загружаем наш файлXML в наш объект, и оттуда мы можем обрабатывать все как обычную структуру Java;

Создать новый документ так же просто, как прочитать его, но сделать все наоборот, как это сделано в приведенном ниже коде.

Во-первых, мы собираемся изменить наш классTutorial, чтобы добавить аннотацииJAXB кgetters иsetters:

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;

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

Чтобы он заработал, нам нужно добавить этотdependency в наш проект.

9. Заключение

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

Вы можете найти полные рабочие образцы для этой статьи в нашем репозитории githere.