Wykład 08
Transkrypt
Wykład 08
Plan Przetwarzanie dokumentów XML i zaawansowane techniki WWW Wykład 07 T. Romańczukiewicz Jagiellonian University 2009/2010 T. Romańczukiewicz XML 07 Plan Plan 1 JAXB T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Plan 1 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodawanie Nowych elementów Marshalling Podsumowanie T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw XML, poprawnie sformuowanie Sposoby opisu XML DTD XML Schema XPATH Sposoby prezentacji CSS XSLT DOM SAX T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw DOM DOM i SAX Parser DOM wczytuje cały dokument do pamieci ˛ i tworzy obiekt DOM przechowujac ˛ dane w strukturze drzewa. DOM pozwala na swobodne poruszanie sie˛ po drzewie dokumentu. W przypadku przetwarzania dużych i skomplikowanych plików XML moga˛ zostać zużyte spore zasoby pamieciowe. ˛ SAX nie wczytuje całego dokumentu lecz działa jak parser strumieniowy sterowany zdarzeniami. Zdarzenia sa˛ zgłaszane gdy zostanie napotkany np element, dane tekstowe czy przestrzeń nazw. Obsługe˛ zdarzeń należy zaimplementować. SAX nie umożliwia uzyskania swobodnego dostepu ˛ do dokumentu XML Przetwarzanie z użyciem SAX jest jednokierunkowe - wcześniej przetworzone dane nie moga˛ być ponownie odczytane bez ponownego uruchomienia całej procedury. Wymagania pamieciowe ˛ SAX sa˛ znacznie mniejsze niż DOM. T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw JAXB JAXB - Java Architecutre for XML Binding Kolejny standard definiujacy ˛ dostep ˛ do plików XML-owych z poziomu jezyka ˛ programowania. Obecnie najbardziej promowany jest przez Suna, ale dostepne ˛ sa˛ również inne implementacje. JAXB nie posiada nie ma tu ogólnego interfejsu do parsowania plików. Interfejs tworzony na podstawie DTD lub XML-Schemy. Dostajemy kompilator schematów (lub dtd), który z tych schematów generuje klasy - dla każdego elementu XML powstaje jedna klasa. Inne podobne narz˛edzia: Castor, XMLBeans (Apache), T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw JAXB a SAX i DOM Zalety w stosunku do DOM-a: mniejsze wymagania pamieciowe, ˛ dzieki ˛ temu, że nie ma narzutu na generyczność DOM-a, w pamieci ˛ jest tylko to co trzeba bardziej intuicyjny dostep ˛ do dokumentu, dzieki ˛ temu nie trzeba znać struktury dokumentu DTD nie jest interpretowane, tylko zaszyte w kodzie - dzieki ˛ temu wieksza ˛ wydajność Zalety w stosunku do SAX-a: łatwiejszy dostep ˛ do pliku - cały plik jest w pamieci ˛ SAX jest read-only, a JAXB umożliwia modyfikacje˛ i zapisywanie do pliku. Model danych w SAX trzeba było tworzyć samodzielnie. T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Podstawowe operacje udostepniane ˛ przez JAXB Generowanie klas. XML Schema jest używana przez kompilator JAXB binding compiler xjc do wygenerowania klas w oparciu o XML Schema Kompilowanie klas. Unmarshalling - zamiana pliku XML na obiekty Javove Modyfikacja dokumentu XML (na kopii z pamieci) ˛ Walidacja - sprawdzenie poprawności z DTD (także dokonywane na dokumencie w pamieci) ˛ Marshalling - zamiana obiektów Javy na dokument XML T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw JAXB - Przykład https://jaxb.dev.java.net/tutorial/section_1_3-Hello-World.html Listing 1: hello.xsd 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="2.0"> <xsd:element name="Greetings" type="GreetingListType"/> <xsd:complexType name="GreetingListType"> <xsd:sequence> <xsd:element name="Greeting" type="GreetingType" maxOccurs="unbounded"/ > </xsd:sequence> </xsd:complexType> <xsd:complexType name="GreetingType"> <xsd:sequence> <xsd:element name="Text" type="xsd:string"/> </xsd:sequence> <xsd:attribute name="language" type="xsd:language"/> </xsd:complexType> </xsd:schema> T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Listing 2: Wywołanie kompilatora JAXB Schema 1 2 3 4 5 6 $ xjc -p hello hello.xsd parsing a schema... compiling a schema... hello/GreetingListType.java hello/GreetingType.java hello/ObjectFactory.java Zostały wygenerowane trzy klasy (wraz z dokładnym javadociem), GreetingType i GreetingListType odpowiadajace ˛ zadeklarowanym typom w schemacie oraz ObjectFactory: Listing 3: GreetingType 1 2 3 4 5 6 7 8 public class GreetingType { (...) public String getText() { return text; } public void setText(String value) { this.text = value; } public String getLanguage() { return language; } public void setLanguage(String value) { this.language = value; (...) } } Klasa GreetingType posiada metody do odczytywania i modyfikowania zawartości tekstowej elementu oraz atrybutu. T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Listing 4: GreetingListType 1 2 3 4 5 6 7 8 9 10 11 12 public class GreetingListType { @XmlElement(name = "Greeting", required = true) protected List<GreetingType> greeting; public List<GreetingType> getGreeting() { if (greeting == null) { greeting = new ArrayList<GreetingType>(); } return this.greeting; } } Aby dodać element do listy: getGreeting().add(newItem); T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Listing 5: ObjectFactory 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class ObjectFactory { private final static QName _Greetings_QNAME = new QName("", "Greetings"); public ObjectFactory() {} /∗ C r e a t e an i n s t a n c e o f G r e e t i n g L i s t T y p e ∗/ public GreetingListType createGreetingListType() { return new GreetingListType(); } public GreetingType createGreetingType() { return new GreetingType(); } @XmlElementDecl(namespace = "", name = "Greetings") public JAXBElement<GreetingListType> createGreetings(GreetingListType value) { return new JAXBElement<GreetingListType>(_Greetings_QNAME, GreetingListType.class, null, value); } } Obiekt zawiera metody wytwórcze (ang. factory methods) dla każdego interfejsu zawartości i elemetu ObjectFactory pozwala tworzyć nowe instancje reprezentacji dokumentu XML T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Przykładowe użycie Listing 6: Hello 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class Hello { private ObjectFactory of; private GreetingListType grList; public Hello(){ of = new ObjectFactory(); grList = of.createGreetingListType(); } public void make( String t, String l ){ GreetingType g = of.createGreetingType(); g.setText( t ); g.setLanguage( l ); grList.getGreeting().add( g ); } public void marshal() { try { JAXBElement<GreetingListType> gl = of.createGreetings( grList ); JAXBContext jc = JAXBContext.newInstance( "hello" ); Marshaller m = jc.createMarshaller(); m.marshal( gl, System.out ); } catch( JAXBException jbe ){ // ... } } } T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Konstruktor tworzy obiekt korzystajac ˛ z metody wytwórczej aby stworzyć element główny XML typu GreetingListType. Metoda make dodaje element do listy wraz z tekstem i atrybutem language. wywołujac ˛ metode˛ marshal lista zamieniana jest na XML i wypisywana na standardowe wyjście. Listing 7: Użycie 1 2 3 4 5 6 Hello h h.make( h.make( h.make( = new Hello(); "Bonjour, madame", "fr" ); "Hey, you", "en" ); "Yo nopot, kivanok", "hu" ); h.marshal(); T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Co prawda dane w XML sa˛ przechowywane zawsze jako tekst, ale dzieki ˛ schematom można dokładniej określić typ tych danych. Dane te moga˛ być mapowane na typy Javy. Przykład: Listing 8: Typy 1 2 3 4 5 6 <xsd:simpleType name="GroupType"> <xsd:restriction base="xsd:int"> <xsd:minInclusive value="1"/> <xsd:maxInclusive value="255"/> </xsd:restriction> </xsd:simpleType> 1 2 3 4 5 public class ElementType { protected int group; public int getGroup() { return group; } public void setGroup(int value) { this.group = value; } Listing 9: Wynik xjc } Typ <xsd:restriction base="xsd:int"> został zinterpretowany jako int, ale w całej klasie nie ma obsługi ograniczeń podanych w schemacie. Uwaga! JAXB nie dostarcza mechanizmów chroniacych ˛ zakres, pattern i inne zaweżenia ˛ schematu. Wszystko to jest sprawdzane dopiero w momencie walidacji. T. Romańczukiewicz XML 07 JAXB XML Schema Type xsd:string xsd:integer xsd:int xsd.long xsd:short xsd:decimal xsd:float xsd:double xsd:boolean xsd:byte xsd:QName xsd:dateTime xsd:base64Binary xsd:hexBinary xsd:unsignedInt xsd:unsignedShort xsd:unsignedByte xsd:time xsd:date xsd:anySimpleType Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Java Data Type java.lang.String java.math.BigInteger int long short java.math.BigDecimal float double boolean byte javax.xml.namespace.QName java.util.Calendar byte[] byte[] long int short java.util.Calendar java.util.Calendar java.lang.String T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Listing 10: Listy 1 2 3 4 5 6 7 <xsd:simpleType name="NumberListType"> <xsd:list itemType="xsd:int"/> </xsd:simpleType> <xsd:simpleType name="StringListType"> <xsd:list itemType="xsd:string"/> <!−− d a n g e r o u s ! −−> </xsd:simpleType> W pierwszym przypadku zostanie utworzona lista protected List<Integer>numbers = new ArrayList<Integer>(); Analogiczie w drugim przypadku, ale w XML reprezentacja˛ bedzie ˛ lista wartości oddzielonych białymi znakami. Jeśli wartości bed ˛ a˛ posiadały białe spacje to może być problem. Zaleca sie˛ zatem stosowanie typów złożonych. T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Również <xsd:all>, <xsd:union>, <xsd:choice> oraz <xsd:sequence> moga˛ być powiazane ˛ z niektórymi strukturami danych Javy takimi jak array, list, structure (lub record) i union. Listing 11: sequence 1 2 3 4 5 6 <xsd:complexType name="PointType"> <xsd:sequence> <xsd:element name="X" type="xsd:int"/> <xsd:element name="Y" type="xsd:int"/> </xsd:sequence> </xsd:complexType> wynik kompilowania Listing 12: sequence w javie 1 2 3 4 5 6 7 8 9 public class PointType { protected int x; protected int y; public public public public int getX() { return x; void setX(int value) { int getY() { return y; void setY(int value) { } this.x = value; } } this.y = value; } } T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Listing 13: xsd:union 1 2 3 4 5 6 7 8 9 10 11 12 13 <xsd:simpleType name="SpeedOrNumberType"> <xsd:union> <xsd:simpleType> <xsd:restriction base="xsd:int"> </xsd:restriction> </xsd:simpleType> <xsd:simpleType> <xsd:restriction base="xsd:string"> <xsd:pattern value="+?d+"/> </xsd:restriction> </xsd:simpleType> </xsd:union> </xsd:simpleType> Jako typ prosty unia zostanie powiazana ˛ ze zmienna˛ typu String. Listing 14: xsd:all 1 2 3 4 5 6 7 8 <xsd:complexType name="DinnerType"> <xsd:all> <xsd:element name="Starter" type="xsd:string" minOccurs="0"/> <xsd:element name="Soup" type="xsd:string" minOccurs="0"/> <xsd:element name="Entree" type="xsd:string"/> <xsd:element name="Dessert" type="xsd:string" minOccurs="0"/> </xsd:all> </xsd:complexType> Zostanie utworzona klasa zawierajaca ˛ zmienne starter, soup itd. Uwaga! maxOccurs nie może mieć wartości wiekszej ˛ niż 1. T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Listing 15: xsd:enumeration 1 2 3 4 5 6 7 8 9 10 <xsd:simpleType name="IXLType"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="eStwA"/> <xsd:enumeration value="eStwS"/> <xsd:enumeration value="SpDrL"/> <xsd:enumeration value="SpDrS"/> <xsd:enumeration value="VGS80"/> </xsd:restriction> </xsd:simpleType> \begin{lstlisting} Listing 16: xsd:enumeration w Javie 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public enum IXLType { E_STW_A("eStwA"), E_STW_S("eStwS"), SP_DR_L("SpDrL"), SP_DR_S("SpDrS"), VGS_80("VGS80"); private final String value; IXLType(String v) { value = v; } public String value() { return value; } } T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Listing 17: xsd:enumeration 1 2 3 4 5 6 7 8 9 <xsd:simpleType name="IXLType"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="eStwA"/> <xsd:enumeration value="eStwS"/> <xsd:enumeration value="SpDrL"/> <xsd:enumeration value="SpDrS"/> <xsd:enumeration value="VGS80"/> </xsd:restriction> </xsd:simpleType> Listing 18: xsd:enumeration w Javie 1 2 3 4 5 6 7 8 9 10 11 12 public enum IXLType { E_STW_A("eStwA"), E_STW_S("eStwS"), SP_DR_L("SpDrL"), SP_DR_S("SpDrS"), VGS_80("VGS80"); private final String value; IXLType(String v) { value = v;} public String value() { return value; } } Nazwy zostały zmienione. T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Można też w taki sposób: Listing 19: xsd:enumeration 1 2 3 4 5 6 7 8 9 <xsd:simpleType name="IXLType"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="eStwA"/> <xsd:annotation><xsd:appinfo> <jxb:typesafeEnumMember name="eStwA"/> </xsd:appinfo></xsd:annotation> ... </xsd:restriction> </xsd:simpleType> Uwaga: w schemacie musi zostać dołaczona ˛ przestrzeń nazw xmlns:jxb="http://java.sun.com/xml/ns/jaxb" Listing 20: xsd:enumeration w Javie 1 2 3 4 5 6 7 8 9 10 11 public enum IXLType { eStwA, eStwS, SpDrL, SpDrS, VGS80; public String value() { ... return name(); } } T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Unmarshalling Po powiazaniu ˛ klas Javy z typami XML Schema przy pomocy xjc można przystapić ˛ do wczytywania danych. Unmarshalling czyli zamiana pliku XML na obiekty Javy Najporościej utworzyć obiekt JAXBContext, nastepnie ˛ Unmarshaller i wywołać metode˛ unmrshal. Obiekt JAXBContext zawiera informacje wiaż ˛ ace ˛ informacje pomiedzy ˛ XML i Java. ˛ Można go utworzyć przy pomocy metody newInstance z parametrem bed ˛ acym ˛ nazwa˛ pakietu utworzonego przez xjc Z tego kontekstu można utworzyć obiekt Unmarshaller, którego metoda unmarshal zwraca obiekt JAXBElement powiazany ˛ z elementem głównym dokumentu. Listing 21: xsd:enumeration w Javie 1 2 3 4 5 6 7 8 public <T> T unmarshal( Class<T> docClass, InputStream inputStream ) throws JAXBException { String packageName = docClass.getPackage().getName(); JAXBContext jc = JAXBContext.newInstance( packageName ); Unmarshaller u = jc.createUnmarshaller(); JAXBElement<T> doc = (JAXBElement<T>)u.unmarshal( inputStream ); return doc.getValue(); } T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Walidacja Przed przekształceniem danych z dokumentu XML na obiekty Javy można wykonać walidacji. Sam JAXB nie stosuje sie˛ do ograniczeń narzuconych przez schemat. Należy zatem te˛ operacje˛ przeprowadzić przed procedura˛ unmarshal i po marshal. Służa˛ do tego obiekt klasy javax.xml.validation.Schema, który zostaje przekazany do obiektu Unmarshaller. Listing 22: Walidacja 1 2 3 4 5 6 7 8 9 10 11 12 13 Schema mySchema; SchemaFactory sf = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); try { mySchema = sf.newSchema( file ); } catch( SAXException saxe ){ / / . . . ( error handling ) mySchema = null; } JAXBContext jc = JAXBContext.newInstance( packagePath ); Unmarshaller u = jc.createUnmarshaller(); u.setSchema( mySchema ); W przypadku gdy walidacja zawiedzie zostanie rzucony wyjatek. ˛ Wyjatki ˛ takie moge˛ być obsługiwane przez interfejs javax.xml.bind.ValidationEventHandler T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Kontekst JAXB Obiekt JAXBContext tworzony jest na samym poczatku ˛ operacji wczytywania pliku XML. Można go utworzyć np. JAXBContext ctxt = JAXBContext.newInstance( "some foo:more.bar"); gdzie dwukropkiem oddziela sie˛ pakiety. Każdy pakiet musi zawierać klase˛ ObjectFactory lub plik jaxb.index: Listing 23: jaxb.index 1 2 3 4 5 # p a c k a g e some . f o o # c l a s s some . f o o . Foo Foo # i n n e r c l a s s some . f o o . Foo . Boo Foo.Boo zawierajacy ˛ liste˛ klas w danym pakiecie. Klasy ObjectFactory sa˛ generowane ze schematu Innym sposobem utworzenia kontekstu jest podanie listy wszystkich klas: JAXBContext ctxt = JAXBContext.newInstance( Foo.class, Bar.class ); T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Użycie danych Dane można odczytywać przy pomocy metod typu get a zapisywać przy pomocy metod typu set. Wygodniej jest jednak stworzyć klasy obsługujace ˛ poszczególne typy schematu. Ich metody moga˛ przetwarzać atrybuty i elementy potomne wywołujac ˛ ich handlery. Listing 24: XML Schema <xsd:complexType name="PersonType"> <xsd:sequence> <xsd:element name="Name" type="NameType"> <xsd:element name="Addr" type="AddrType" minOccurs="0"> <xsd:element name="Child" type="ChildType" minOccurs="0" maxOccurs=" unbounded"> 6 </xsd:sequence> 7 <xsd:attribute name="resident" type="xsd:boolean"/> 8 </xsd:complexType> 1 2 3 4 5 9 10 11 12 13 14 <xsd:complexType name="ChildType"> <xsd:complexContent> <xsd:extension base="PersonType"/> </xsd:complexContent> </xsd:complexType> T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Użycie danych c.d Listing 25: Handler classes 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 abstract class Handler { protected static Map<Class<?>,Handler> ourClass2Conv = new HashMap<Class<?>, Handler>(); static { ourClass2Conv.put( PersonType.class, new PersonHandler() ); ourClass2Conv.put( NameType.class, new NameHandler() ); ourClass2Conv.put( AddrType.class, new AddrHandler() ); ourClass2Conv.put( ChildType.class, new ChildHandler() ); // ... } public abstract void handle( Object o ); protected void process( Object obj ){ if( obj != null ){ Handler h = ourClass2Conv.get( obj.getClass() ); if( h != null ){ h.handle( obj ); } } } protected <T> void processList( List<T> list ){ for( T obj: list ){ Handler h = this.getHandler( obj ); h.process( obj ); } } } T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Użycie danych c.d Listing 26: Handler classes 1 2 3 4 5 6 7 8 class PersonHandler extends Handler { public void handle( Object o ){ PersonType p = (PersonType)o; process( p.getName() ); if( p.isResident() ){ process( p.getAddr() ); processList( p.getChild ); } } T. Romańczukiewicz XML 07 } JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw ObjectFactory Jedna˛ z klas wygenerowanych przez xjc jest klasa ObjectFactory. Klasa ta zawiera metody do tworzenia elementów reprezentowanych przez objekty JAXBElement<?>: Listing 27: ObjectFactory 1 2 3 ObjectFactory objFact = new ObjectFactory(); RulebaseType rulebase = objFact.createRulebaseType(); JAXBElement<RulebaseType> doc = objFact.createRulebase( rulebase ); - znacznik elementu głównego. proste elementy nie potrzebuja˛ JAXBElement<?>. Można je utworzyć bezpośrednio z wywołania metody: rulebase ModuleType module = objFact.createModuleType(); Objekt JAXBElement<?> jest wymagany w przypadku elementów zawierajacych ˛ sekwencje˛ elementów tego samego typu ale o innych znacznikach: Listing 28: Przykład 1 2 3 4 5 6 7 8 <xsd:complexType name="FooBarListType"> <xsd:sequence> <xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:element name="foo" type="FooBarType"/> <xsd:element name="bar" type="FooBarType"/> </xsd:choice> </xsd:sequence> </xsd:complexType> T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw ObjectFactory c.d. Listing 29: ObjectFactory 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 FooBarListType fblElem = objFact.createFooBarListType(); List<JAXBElement<FooBarType>> fbList = fblElem.getFooOrBar(); / / create a " foo " element FooBarType foo = objFact.createFooBarType(); / / . . . ( add a t t r i b u t e s and c o m p o n e n t s t o f o o ) / / C r e a t e t h e e l e m e n t <f o o > . . . < / f o o > JAXBElement<FooBarType> fooElem = objFact.createFooBarTypeFoo( foo ); / / Add i t t o i t s p a r e n t ’ s l i s t . fbList.add( fooElem ); / / c r e a t e a " bar " e l e m e n t FooBarType bar = objFact.createFooBarType(); / / . . . ( add a t t r i b u t e s and c o m p o n e n t s t o b a r ) / / C r e a t e t h e e l e m e n t <bar > . . . < / bar > JAXBElement<FooBarType> barElem = objFact.createFooBarTypeBar( bar ); / / Add i t t o i t s p a r e n t ’ s l i s t . fbList.add( barElem ); T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Aby dodać element potomny x wewnatrz ˛ elementu current (np. głównego) należy Stworzyć element xElem przy pomocy metody createX. Dodać nowo stworzony current.setX( xElem ). Powtórzyć ten proces rekurencyjnie dla elementów potomnych nowego elementu Listing 30: Dodawanie nowych obiektów 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 / / C r e a t e o r d e r and i n s e r t i n t o p−l e v e l document , a l i s t o f o r d e r s OrderType orderElem = objFact.createOrderType(); folder.getOrders().add( orderElem ); / / C r e a t e and i n s e r t t h e c u s t o m e r e l e m e n t . CustomerType custElem = objFact.createCustomerType(); orderElem.setCustomer( custElem ); / / Complete customer . custElem.setId( custId ); custElem.setName( custName ); / / C r e a t e and add i t e m e l e m e n t s . List<ItemType> itemList = orderElem.getItems(); for( Item item: items ){ ItemType itemElem = objFact.createItemType(); itemList.add( itemElem ); itemElem.setId( item.id ); itemElem.setQuantity( item.qtty ); } T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Dodawanie Nowych elementów c.d. Listing 31: schemat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <xsd:complexType name="CustomerType"> <xsd:sequence> <xsd:element name="id" type="xsd:int"/> <xsd:element name="name" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="ItemType"> <xsd:sequence> <xsd:element name="id" type="xsd:string"/> <xsd:element name="quantity" type="xsd:int"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="OrderType"> <xsd:sequence> <xsd:element name="customer" type="CustomerType"/> <xsd:element name="items" type="ItemType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:element name="folder"> <xsd:complexType> <xsd:sequence> <xsd:element name="orders" </xsd:sequence> </xsd:complexType> </xsd:element> type="OrderType" maxOccurs="unbounded"/> T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw Marshalling Końcowym etapem tworzenia lub modyfikowania dokumentu XML jest procedura zwana Marshalling. Po utworzeniu obiektu Marshaller z obiektu JAXBContext można ustawić szereg właściwości (np ustawianie formatowania wydruku, sposobu dołaczenia ˛ schematu, strony kodowej itp.) Listing 32: Marshalling 1 2 3 4 5 6 7 8 9 10 11 12 import java.io.*; import javax.xml.bind.* void writeDocument( Object document, String pathname ) throws JAXBException, IOException { Class<T> clazz = document.getValue().getClass(); JAXBContext context = JAXBContext.newInstance( clazz.getPackage().getName() ); Marshaller m = context.createMarshaller(); m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE ); m.marshal( document, new FileOutputStream( pathname ) ); } T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw JAXB JAXB jest architektura˛ powiaza ˛ ń pomiedzy ˛ XML i klasami Javy Najpierw na podstawie XML Schema generowane sa˛ klasy odpowiadajace ˛ typom zadeklarowanym w schemacie. Klasy te zawieraja˛ metody do czytania i manipulacji obiektami reprezentujacymi ˛ elementy XML Typy Javy nie zachowuja˛ restrykcji nakładanych w schemacie. Przed wczytaniem danych lub po ich zapisaniu do pliku możliwa jest walidacja. Generowana jest też klasa ObjectFactory pozwalajaca ˛ tworzyć nowe instancje reprezentacji dokumentu XML Dokument XML wczytywany jest w trakcie procedury Unmarshalling na podstawie kontekstu zawierajacego ˛ informacje o pakiecie. Po modyfikacji zmiennych można zapisać dane do pliku przy pomocy metody Marshalling. T. Romańczukiewicz XML 07 JAXB Przypomnienie Wstep ˛ Przykład Typy danych Unmarshalling Dodaw JAXB a DOM i SAX DOM wczytywał cały dokument do pamieci ˛ Dane przechowywane były w uniwersalnej strukturze drzewa Dzieki ˛ odpowiednim metodom można sie˛ było poruszać po całym drzewie dokumentu SAX przetwarzał dokument w trakcie czytania. Aby stworzyć model danych należało samemu go zaimplementować. SAX przetwarzał dokument jednokierunkowo. JAXB sam tworzy strukture˛ danych na podstawie istniejacego ˛ już schematu. Do danych jest dostep ˛ cały czas. T. Romańczukiewicz XML 07