Katalog książek cz. 2 Odczytywanie danych z XML Do ćwiczenia dołączony jest plik books.xml zawierający pełen katalog książek. Poniższy listing zawiera przykładowy fragment danych w stosowanym formacie. <?xml version="1.0" encoding="utf-8" standalone="yes"?> <books> <book id="1"> <author>brett D. McLaughlin, Justin Edelson</author> <isbn>978-83-246-6075-9</isbn> <pages>0</pages> <publisher>helion</publisher> <title>java i XML. Wydanie III</title> <year>2007</year> </book> <book id="2"> <author>testowy autor</author> <isbn>123-45-678-9012-3</isbn> <pages>0</pages> <publisher>helion</publisher> <title>testowy tytuł</title> <year>2007</year> </book> </books> W kolejnych krokach rozbudujemy kod z ćwiczenia 1 o odczytywanie książek z pliku XML z użyciem standardu JAXB. 1) Otwórz projekt z ćwiczenia nr 1. Do katalogu projektu skopiuj plik books.xml dołączony do ćwiczenia. 2) Uzupełnij klasę Book o odpowiednie adnotacje: @XmlType(name = "book") Adnotację XmlType umieść przed nagłówkiem klasy Book. Informuje ona biblioteki JAXB o tym, że klasa Book będzie odpowiadać typowi o nazwie book w dokumencie XML. @XmlAttribute Adnotację XmlAttribute umieść przed metodą getid(). Informuje ona o tym, że właściwość id ma zostać zmapowana w sposób inny, niż domyślny na atrybut XML (domyślnie zostałaby zmapowana na element o nazwie id ). Strona 1
3) Stwórz klasę BookList, zawierającą listę książek oraz spełniającą wymagania JavaBean: package books; import java.util.list; public class BookList { private List<Book> books; public List<Book> getbooks() { return books; public void setbooks(list<book> books) { this.books = books; Uzupełnij klasę o odpowiednie adnotacje: @XmlRootElement(name = "books") przed nagłówkiem klasy @XmlElement(name = "book") przed metodą getbooks() Po uzupełnieniu pełny kod klasy BookList powinien wyglądać następująco: package books; import java.util.list; import javax.xml.bind.annotation.xmlelement; import javax.xml.bind.annotation.xmlrootelement; @XmlRootElement(name = "books") public class BookList { private List<Book> books; @XmlElement(name = "book") public List<Book> getbooks() { return books; public void setbooks(list<book> books) { this.books = books; Strona 2
4) Zmień kod metody main() w klasie Main, tak żeby odczytywał listę książek z pliku books.xml. Poniższe dwa listingi przedstawiają sam kod do odczytania danych z pliku XML z użyciem JAXB, a następnie całą metodę main(), po wymaganych uzupełnieniach i modyfikacjach. Odczyt listy książek z pliku XML: try { JAXBContext context = JAXBContext.newInstance(BookList.class); Unmarshaller um = context.createunmarshaller(); FileReader fr = new FileReader("books.xml"); BookList bl = (BookList) um.unmarshal(fr); fr.close(); catch (JAXBException e) { e.printstacktrace(); catch (IOException e) { e.printstacktrace(); Cała metoda main() po wszystkich modyfikacjach: public static void main(string[] args) { try { JAXBContext context = JAXBContext.newInstance(BookList.class); Unmarshaller um = context.createunmarshaller(); FileReader file = new FileReader("books.xml"); BookList books = (BookList)um.unmarshal(file); file.close(); BookManager bm = new BookManager( books.getbooks() ); List<Book> bs = bm.searchbytitle("java"); System.out.println(bs); catch (Exception ex) { ex.printstacktrace(); Strona 3
Zadanie 1 Zapis danych do XML odbywa się bardzo podobnie, jak odczyt. Aby zapisać pewien obiekt do XML, należy: przygotować kontekst JAXB (jak w powyższym kodzie); przygotować obiekt serializujący (zwany w JAXB marshallerem ), wywołując metodę createmarshaller(); wywołać metodę marshal(), przekazując do niej obiekt do zapisania oraz plik lub strumień wyjściowy. Klasa, do której należy zapisywany obiekt, musi posiadać odpowiednie adnotacje JAXB, w tym adnotację XmlRootElement. W naszym projekcie bezpośrednio zapisywać można obiekty klasy BookList. Dopisz do metody main() kod realizujący następujące zadanie: stwórz nową książkę; jako autora podaj swoje imię i nazwisko, jako tytuł Laboratorium: Java i XML ; dodaj tę książkę do listy w utworzonym wcześniej obiekcie BookManager; wyszukaj książki ze słowem Java w tytule; wynik opakuj w klasę BookList (czyli utwórz nowy obiekt klasy BookList, metodą setbooks() zapisz w nim listę znalezionych książek); zapisz powstałą listę książek do nowego pliku XML o nazwie lab3.xml. Zadanie 2 Zrób kopię projektu pierwotną wersję zachowaj na potrzeby kolejnych zajęć; kopii użyj w bieżącym zadaniu. Przyjrzyj się różnicy pomiędzy plikami books.xml i books.2.xml w pierwszym przypadku autorzy książki są podani w jednym elemencie XML, po przecinku: <author>jan Kowalski, Jan Nowak</author> w drugim pliku autorzy są rozbici na osobne elementy: <authors> <author>jan Kowalski</author> <author>jan Nowak</author> </authors> Strona 4
Zmodyfikuj klasę Book tak, aby była zgodna z drugą wersją (plik books.2.xml): o zamiast pola String author umieść pole: List<String> authors o usuń meotdy getauthor() i setauthor(), zastąp je odpowiednimi metodami getauthors() i setauthors() (skutkiem ubocznym będą błędy kompilacji w klasie BookManager dla uproszczenia możesz usunąć z klasy BookManager kod wyszukujący książki po autorze); o do poprawnej serializacji/deserializacji autorów konieczne będzie użycie adnotacji @XmlElementWrapper przykład jej użycia znajdziesz m.in. tutaj: https://jaxb.java.net/tutorial/section_6_2_7_7-wrapping-repeated-elements- XmlElementWrapper.html Zadanie 3 W pliku books.3.xml znajdziesz kolejną wersję formatu XML. Tym razem element publisher jest elementem złożonym, zawiera zagnieżdżone elementy name i url. Zmodyfikuj kod programu tak, by możliwe było odczytanie nowego formatu pliku. Konieczne będzie stworzenie klasy Publisher i odpowiednie zmapowanie jej do XML. Zadanie dodatkowe Przygotuj analogiczny kod dla danych przygotowanych w ramach poprzedniego ćwiczenia (własny plik XML i schemat XML Schema). Strona 5