
Нельзя обойти вниманием XML Parseer JAXB. Рассмотрим его работу на примере ручного описания и авто генерации классов.
Задание:
Parsing XML с помощью JAXB. Классы описать несколькими способами. Проработать пример с @XmlElementWrapper, с multi namespace.
Использовал:
JAXB | XSD | XML |
Частая задача, работа с XML, поэтому решения которые позволяют решать задачи быстро очень интересны широкой публике и чаще всего используются при написании кода.
Основной принцип следующий: Получили в работу XML / либо сгенерировали XML.
– Необходимо по ней создать XSD схему. (Два варианта, ручной и автогенерация);
– По XSD сгенерировать JAXB классы описывающие элементы, либо описать вручную;
– Unmarshaller XML;
Для генерации XSD можно воспользоваться online генераторами, к примеру Freeformatter.
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="ActorCast"> <xs:complexType> <xs:sequence> <xs:element name="Cast" maxOccurs="unbounded" minOccurs="0"> <xs:complexType> <xs:sequence> <xs:element name="Character"> <xs:complexType> <xs:sequence> <xs:element type="xs:string" name="FirstName"/> <xs:element type="xs:string" name="LastName"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Actor"> <xs:complexType> <xs:sequence> <xs:element type="xs:string" name="FirstName"/> <xs:element type="xs:string" name="LastName"/> <xs:element type="xs:string" name="BirthDay"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute type="xs:byte" name="id" use="optional"/> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> |
Используя Idea Intellij и плагин WebService по XSD генерируем JAXB классы.
Ну и немного кода, Unmarshaller XML.
//Start Unmarshalling JAXBContext jaxbContext = JAXBContext.newInstance(ActorCast.class); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); ActorCast jaxbElement = (ActorCast) unmarshaller.unmarshal(new File(XMLFILE)); //Stop Unmarshalling List<ActorCast.Cast> cast = jaxbElement.getCast(); for(ActorCast.Cast cst : cast){ System.out.println("========================================"); System.out.println("Actor: " +cst.getActor().getFirstName()+" "+cst.getActor().getLastName()+", "+cst.getActor().getBirthDay()); System.out.println("Character: " +cst.getCharacter().getFirstName()+" "+cst.getCharacter().getLastName()); } |
Для понимания процесса, теперь опишем модель XML вручную. Итак имеется XML:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <ActorCast> <Cast id="1"> <Character> <FirstName>Daenerys</FirstName> <LastName>Targaryen</LastName> </Character> <Actor> <FirstName>Emilia</FirstName> <LastName>Clarke</LastName> <BirthDay>23 October 1986</BirthDay> </Actor> </Cast> </ActorCast> |
По спецификации, XML наша содержит:
Root element– ActorCast. Он может быть только 1 в документе.
XML prolog
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
XML Elements – Cast, Character,FirstName …
XML Attribute – id. Значение атрибутов всегда должно заключаться в кавычки. И Value атрибута id равно 1.
Для каждой ноды XML в JAXB есть соответствующая аннотация.
Root element @XmlRootElement
XML Elements @XmlElement
XML Attribute @XmlAttribute
XML Tree
Добавилось несколько аннотаций:
@XmlAccessorType(XmlAccessType.FIELD) Доступ непосредственно к полям класса.
@Getter, @Setter, @ToString Аннотации от библиотеки lombok, код более читабелен, стандартные геттеры и сеттеры.
Не использовали еще одну полезную аннотацию: @XmlElementWrapper Указывает на то что, элемент является оберткой, в нашем случае по сути это элемент Cast.
Зачастую, рабочие XML не всегда выглядят так дружественно и имеют простую структуру, как в примере с Actors. Добавляется пространство имен – XML Namespaces. Основное предназначение Namespaces, избежание конфликтов наименований элементов.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <ActorCast xmlns:ch="http://www.gotoqa.ru/character/" xmlns:ac="http://www.gotoqa.ru/actor/"> <Cast id="1"> <ch:Character> <ch:FirstName>Daenerys</ch:FirstName> <ch:LastName>Targaryen</ch:LastName> </ch:Character> <ac:Actor> <ac:FirstName>Emilia</ac:FirstName> <ac:LastName>Clarke</ac:LastName> <ac:BirthDay>23 October 1986</ac:BirthDay> </ac:Actor> </Cast> </ActorCast> |
Таким образом элементы области ch вне видимости в зоне ac и наоборот.
JAXB все аннотации имеют параметр namespace
@XmlRootElement(name = “ActorCast”, namespace = “http://www.gotoqa.ru/character/”)
Ссылка на полную версию проекта на GitHub:
Github JAXBParsingProject