V jednom z předchozích příspěvků jsem se věnoval základní práci s JAXB, kde jsem používal pouze dvě anotace a to @XmlRootElement
a @XmlType
. Podívejme se na část vytvořeného xml souboru.
<company> <centers> <code>METPRG</code> <description>Office center Metronom in Prague</description> <rooms> <code>A02</code> <numberOfSeats>14</numberOfSeats> </rooms> <rooms> <code>A13</code> <numberOfSeats>42</numberOfSeats> </rooms> <rooms> <code>B08</code> <numberOfSeats>22</numberOfSeats> </rooms> </centers> <centers> <code>AVIPRG</code> <description>Office center Aviatica in Prague</description> <rooms> <code>AA41</code> <numberOfSeats>70</numberOfSeats> </rooms> <rooms> <code>CA12</code> <numberOfSeats>38</numberOfSeats> </rooms> ...
Company obsahuje seznam elementů center a ty v sobě mají seznam elementů room. Když se podíváte pečlivěji, uvidíte, že každý element center se jmenuje centers a každý element room se jmenuje rooms. Určitě by to lépe vypadalo, kdyby se tyto elementy jmenovaly center a room. Nebo možná ještě lépe, kdyby se element center jmenoval jednoznačněji business_center. Jak center tak room obsahují element code. Bylo čitelnější, kdyby se jmenovaly center_code a room_code. A také kořenový element company by mohl obsahovat ještě atribut s názvem společnosti. To vše je možné, když použijeme další anotace, které JAXB nabízí.
Anotace @XmlAccessorType říká, že každý field (nestatická a netransientní proměnná – to jsou v tomto příkladu všechny) bude svázán s xml elementem.
Anotaci @XmlElementWrapper použijeme, když pracujeme se seznamem. Vytvoříme element, který bude v sobě obsahovat jednotlivé elementy seznamu.
Anotace @XmlAttribute nevytvoří xml element, ale atribut. Pomocí hodnoty, kterou přiřadíme do name nastavíme atributu název.
Když použijeme anotaci @XmlElement, můžeme předat hodnotu name a tím nastavíme názvem xml elementu.
Jasnější to bude na příkladu.
App.java
import java.io.File; import java.util.ArrayList; import java.util.Arrays; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; public class App { public static void main(String[] args) throws JAXBException { // marshal JAXBContext context = JAXBContext.newInstance(Company.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); File file = new File("company.xml"); // writes to file marshaller.marshal(createCompany(), file); // writes to System.out marshaller.marshal(createCompany(), System.out); // unmarshal Unmarshaller unmarshaller = context.createUnmarshaller(); Company company = (Company)unmarshaller.unmarshal(file); // print unmashalled object System.out.println(); for (Center center : company.getCenters()) { System.out.println(center.getCode() + " - " + center.getDescription()); for (Room room : center.getRooms()) { System.out.println("room: " + room.getCode() + "\t number of seats: " + room.getNumberOfSeats()); } System.out.println(); } } private static Company createCompany() { Center metronomPrague = new Center(); metronomPrague.setCode("METPRG"); metronomPrague.setDescription("Office center Metronom in Prague"); metronomPrague.setRooms( Arrays.asList( new Room("A02", 14), new Room("A13", 42), new Room("B08", 22))); Center aviaticaPrague = new Center(); aviaticaPrague.setCode("AVIPRG"); aviaticaPrague.setDescription("Office center Aviatica in Prague"); aviaticaPrague.setRooms( Arrays.asList( new Room("AA41", 70), new Room("CA12", 38), new Room("CA18", 24), new Room("CB52", 88), new Room("CD11", 62))); Company company = new Company(); company.setName("1. Nájemní, s.r.o."); company.setCenters(new ArrayList<>()); company.getCenters().add(metronomPrague); company.getCenters().add(aviaticaPrague); return company; } }
Company.java
import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Company { @XmlAttribute(name = "company_name") private String name; @XmlElement(name = "business_center") @XmlElementWrapper(name = "business_centers") private List<Center> centers; // getters and setters }
Oproti kódu z předchozího příspěvku jsem přidal field private String name
a označil jej anotací @XmlAttribute(name = „company_name“), která vytvoří xml atribut s názvem company_name. V App.java přiřazujeme do proměnné name hodnotu „1. Nájemní, s.r.o“ takže v xml souboru to bude vypadat následovně:
<company company_name="1. Nájemní, s.r.o."> ... </company>
Anotace @XmlElementWrapper(name = „business_centers“) vytvoří xml element business_center a v něm budou obsaženy jako elementy všechny objekty ze seznamu. Anotace @XmlElement(name = „business_center“) nastaví název každého elementu v listu na business_center.
<business_centers> <business_center> ... </business_center> <business_center> ... </business_center> </business_centers>
Center.java
import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlType; @XmlType @XmlAccessorType(XmlAccessType.FIELD) public class Center { @XmlElement(name = "center_code") private String code; @XmlElement(name = "center_description") private String description; @XmlElementWrapper(name = "rooms") @XmlElement(name = "room") private List<Room> rooms; // getters and setters }
Anotace @XmlElement(name = „center_code“) nastaví xml elementu název center_code. Stejné je to pro @XmlElement(name = „center_description“).
<center_code>METPRG</center_code> <center_description>Office center Metronom in Prague</center_description>
Anotace @XmlElementWrapper(name = „rooms“) a @XmlElement(name = „room“) jsou obdobné jako ty, co jsme si vysvětlili na třídě Company.
Room.java
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; @XmlType @XmlAccessorType(XmlAccessType.FIELD) public class Room { @XmlElement(name = "room_code") private String code; private int numberOfSeats; public Room() {} // setters and getters }
V této třídě již není nic nového. Výsledný soubor vypadá následovně.
Company.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <company company_name="1. Nájemní, s.r.o."> <business_centers> <business_center> <center_code>METPRG</center_code> <center_description>Office center Metronom in Prague</center_description> <rooms> <room> <room_code>A02</room_code> <numberOfSeats>14</numberOfSeats> </room> <room> <room_code>A13</room_code> <numberOfSeats>42</numberOfSeats> </room> <room> <room_code>B08</room_code> <numberOfSeats>22</numberOfSeats> </room> </rooms> </business_center> <business_center> <center_code>AVIPRG</center_code> <center_description>Office center Aviatica in Prague</center_description> <rooms> <room> <room_code>AA41</room_code> <numberOfSeats>70</numberOfSeats> </room> <room> <room_code>CA12</room_code> <numberOfSeats>38</numberOfSeats> </room> <room> <room_code>CA18</room_code> <numberOfSeats>24</numberOfSeats> </room> <room> <room_code>CB52</room_code> <numberOfSeats>88</numberOfSeats> </room> <room> <room_code>CD11</room_code> <numberOfSeats>62</numberOfSeats> </room> </rooms> </business_center> </business_centers> </company>