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

Что такое XML? Аббревиатура «XML» означает - расширяемый язык разметки. Он имеет структуру разметки, аналогичную HTML, и был разработан для хранения и передачи данных. Он определяет набор правил, которые делают его читаемым как человеком, так и машиной. Несмотря на то, что XML является языком разметки, таким как HTML, он обычно используется для обмена данными между веб-службами, серверными приложениями и интерфейсами, как JSON, и считается его предшественником. Если вам интересно читать о чтении и записи JSON на Java [/ r

Что такое XML?

Аббревиатура "XML" означает - е X tensible M arkup L anguage. Он имеет структуру разметки, аналогичную HTML, и был разработан для хранения и передачи данных. Он определяет набор правил, которые делают его читаемым как человеком, так и машиной.

Несмотря на то, что XML является языком разметки, таким как HTML, он обычно используется для обмена данными между веб-службами, серверными приложениями и интерфейсами, как и JSON, и считается его предшественником.

Если вам интересно читать о чтении и записи JSON на Java , мы уже рассмотрели это!

Важно отметить, что XML не имеет предопределенного набора тегов, таких как HTML, а скорее определяется пользователем. Именно эта гибкость привела к созданию множества форматов документов, таких как RSS , Atom , SOAP и XHTML . По сути, все эти форматы являются подмножествами XML.

Давайте посмотрим на простой XML-документ, который реплицирует тот же объект, который мы использовали ранее в отношении JSON:

 <?xml version="1.0" encoding="UTF-8"?> 
 <person> 
 <age>31</age> 
 <hobbies> 
 <element>Football</element> 
 <element>Swimming</element> 
 </hobbies> 
 <isMarried>true</isMarried> 
 <kids> 
 <person> 
 <age>5</age> 
 <name>Billy</name> 
 </person> 
 <person> 
 <age>3</age> 
 <name>Milly</name> 
 </person> 
 </kids> 
 <name>Benjamin Watson</name> 
 </person> 

Ключевое различие между XML и JSON заключается в том, что мы определяем этот файл с версией XML и кодируем в начале документа с помощью <?xml> . Еще одно отличие состоит в том, что каждое свойство объекта должно быть заключено в отдельный тег - <age>31</age> . Элементы массива не могут быть указаны без тега, поэтому, чтобы перечислить их, мы помещаем их в <element>...</element> внутри <hobbies>...</hobbies> .

JAXB

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

Java, однако, обеспечивает удобный способ манипулирования XML с использованием структуры под названием J AVA rchitecture для X ML B inding или JAXB для краткости. Это позволяет нам отображать объект Java в документы XML и наоборот. JAXB был впервые представлен в JDK 1.6 и недоступен в предыдущих версиях.

Поскольку JAXB является стандартной структурой JDK, нет необходимости включать в проект какие-либо внешние зависимости для JDK 1.6+.

Примечание. Если вы используете Java 9 или выше, вам следует включить в команду javac дополнительный параметр. Если вы используете IDE, например IntelliJ IDEA или Eclipse, поищите дополнительную настройку параметров компилятора и убедитесь, что она включает --add-modules java.xml.bind .

В случае IntelliJ IDEA он находится в Preferences -> Build, Execution, Deployment -> Compiler -> Java Compiler .

Если вы все равно будете получать такие ошибки, как Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/JAXBContext даже после добавления дополнительной опции компилятора, добавьте следующие зависимости Maven:

 <dependency> 
 <groupId>javax.xml.bind</groupId> 
 <artifactId>jaxb-api</artifactId> 
 <version>2.2.11</version> 
 </dependency> 
 <dependency> 
 <groupId>com.sun.xml.bind</groupId> 
 <artifactId>jaxb-core</artifactId> 
 <version>2.2.11</version> 
 </dependency> 
 <dependency> 
 <groupId>com.sun.xml.bind</groupId> 
 <artifactId>jaxb-impl</artifactId> 
 <version>2.2.11</version> 
 </dependency> 
 <dependency> 
 <groupId>javax.activation</groupId> 
 <artifactId>activation</artifactId> 
 <version>1.1.1</version> 
 </dependency> 

Концепции ядра JAXB называются сортировочные и демаршалинг . Неудивительно, что они представлены классами Marshaller и Unmarshaller .

Маршаллинг - это процесс преобразования объектов Java в XML, а демаршаллинг - это процесс преобразования XML в объекты Java.

JAXB настраивается с использованием аннотаций, которые импортируются из пакета javax.xml.bind.annotations

Давайте определим класс Java, который представляет человека, описанного в нашем XML-документе:

 @XmlRootElement 
 public class Person { 
 
 public Person(String name, int age, boolean isMarried, List<String> hobbies, List<Person> kids) { 
 this.name = name; 
 this.age = age; 
 this.isMarried = isMarried; 
 this.hobbies = hobbies; 
 this.kids = kids; 
 } 
 
 public Person(String name, int age) { 
 this(name, age, false, null, null); 
 } 
 
 private String name; 
 private Integer age; 
 private Boolean isMarried; 
 private List<String> hobbies; 
 private List<Person> kids; 
 
 public String getName() { 
 return name; 
 } 
 
 public void setName(String name) { 
 this.name = name; 
 } 
 
 public int getAge() { 
 return age; 
 } 
 
 public void setAge(int age) { 
 this.age = age; 
 } 
 
 public boolean isMarried() { 
 return isMarried; 
 } 
 
 @XmlElement(name = "isMarried") 
 public void setMarried(boolean married) { 
 isMarried = married; 
 } 
 
 @XmlElementWrapper(name = "hobbies") 
 @XmlElement(name = "element") 
 public List<String> getHobbies() { 
 return hobbies; 
 } 
 
 public void setHobbies(List<String> hobbies) { 
 this.hobbies = hobbies; 
 } 
 
 public List<Person> getKids() { 
 return kids; 
 } 
 
 @XmlElementWrapper(name = "kids") 
 @XmlElement(name = "person") 
 public void setKids(List<Person> kids) { 
 this.kids = kids; 
 } 
 
 @Override 
 public String toString() { 
 return "Person{" + 
 "name='" + name + '\'' + 
 ", age=" + age + 
 ", isMarried=" + isMarried + 
 ", hobbies=" + hobbies + 
 ", kids=" + kids + 
 '}'; 
 } 
 } 

@XmlRootElement - сопоставляет класс или тип перечисления с элементом XML. Он описывает корневой элемент XML-документа и должен быть указан в объявлении класса Person

@XmlElementWrapper - генерирует элемент-оболочку вокруг XML-представления, в нашем случае List Элементы списка следует указывать явно с @XMLElement аннотации @XMLElement.

@XMLElement - сопоставляет свойство объекта Java с элементом XML, производным от имени свойства. Чтобы указать другое имя свойства XML, мы включаем его как параметр String в объявление аннотации, то есть (name = "person") .

Демаршаллинг

Простейший пример техники маршалинга потребует от нас создать JAXBContext , передав Person.class в качестве единственного входного параметра его конструктора.

Затем создается createUnmarshaller() , а экземпляр фактического Person создается его методом unmarshal() .

Обязательно используйте явное приведение типов, так как unmarshal метод возвращает тип Object:

 public class Solution { 
 public static void main(String[] args) throws Exception { 
 Person person = XMLtoPersonExample("person.xml"); 
 System.out.println(person); 
 } 
 
 private static Person XMLtoPersonExample(String filename) throws Exception { 
 File file = new File(filename); 
 JAXBContext jaxbContext = JAXBContext.newInstance(Person.class); 
 
 Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 
 return (Person) jaxbUnmarshaller.unmarshal(file); 
 } 
 } 

После запуска этого кода вы должны увидеть что-то вроде:

 Person{name='Benjamin Watson', age=31, isMarried=true, hobbies=[Football, Swimming], kids=[Person{name='Billy', age=5, isMarried=null, hobbies=null, kids=null}, Person{name='Milly', age=3, isMarried=null, hobbies=null, kids=null}]} 

Маршаллинг

Чтобы продемонстрировать способность JAXB записывать XML-файл с использованием объекта Java в качестве источника, мы добавим следующий метод:

 private static void personToXMLExample(String filename, Person person) throws Exception { 
 File file = new File(filename); 
 JAXBContext jaxbContext = JAXBContext.newInstance(Person.class); 
 
 Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); 
 
 jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
 jaxbMarshaller.marshal(person, file); 
 jaxbMarshaller.marshal(person, System.out); 
 } 

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

Добавив вызов этого метода в качестве последней строки в Solution.main() например:

 personToXMLExample("person-output.xml", person); 

и запустив его, мы получим досадное исключение.

 Exception in thread "main" java.lang.NullPointerException 
 at com.stackabuse.xml.Person.isMarried(Person.java:49) 
 at com.stackabuse.xml.Person$JaxbAccessorM_isMarried_setMarried_boolean.get(MethodAccessor_Boolean.java:61) 
 ... 

Мы допустили ошибку, установив isMarried поля isMarried в класс-оболочку Boolean а тип возвращаемого значения getter isMarried() в примитивное boolean , что приводит к тому, что JAXB пытается распаковать null и в результате выбрасывает NullPointerException .

Быстрое и простое решение этой проблемы - выровнять эти два значения либо с boolean Boolean .

После устранения проблемы мы получим следующий вывод как в консоль, так и в файл:

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
 <person> 
 <age>31</age> 
 <hobbies> 
 <element>Football</element> 
 <element>Swimming</element> 
 </hobbies> 
 <kids> 
 <person> 
 <age>5</age> 
 <name>Billy</name> 
 </person> 
 <person> 
 <age>3</age> 
 <name>Milly</name> 
 </person> 
 </kids> 
 <isMarried>true</isMarried> 
 <name>Benjamin Watson</name> 
 </person> 

Как мы видим, он полностью идентичен исходному XML-файлу, который мы упорядочили в объект person

Заключение

Чтение и запись XML на Java можно легко выполнить с помощью инфраструктуры JAXB. Используя аннотации, мы определяем правила отображения между Java-классами и XML-документами, которые представляют их объекты.

XML часто считается устаревшим форматом, который уступает JSON. Однако знание того, как его читать и писать с помощью Java, является полезным навыком для любого разработчика программного обеспечения, поскольку многие службы в Интернете все еще используют его и еще не имеют JSON API. Это также относится ко многим форматам файлов, в которых данные хранятся в файлах в формате XML.

Хотя, если вам больше нравится JSON, я бы посоветовал прочитать о чтении и записи JSON на Java, мы это тоже рассмотрели!

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus